Не уверен, что вы найдете встроенную функцию, поэтому вот домашний напиток, использующий argsort.
def running_count(arr):
idx = arr.argsort(kind='mergesort')
sarr = arr[idx]
neq = np.where(sarr[1:] != sarr[:-1])[0] + 1
run = np.ones(arr.shape, int)
run[neq[0]] -= neq[0]
run[neq[1:]] -= np.diff(neq)
res = np.empty_like(run)
res[idx] = run.cumsum()
return res
Например:
>>> running_count(arr)
array([1, 1, 2, 1, 1, 2, 3])
>>> running_count(np.array(list("xabaaybeeetz")))
array([1, 1, 1, 2, 3, 1, 2, 1, 2, 3, 1, 1])
Объяснитель:
Мысначала отсортируйте, используя argsort, потому что нам нужны индексы, чтобы в конце вернуться к исходному порядку.Здесь важно иметь стабильную сортировку, поэтому следует использовать медленную сортировку слиянием.
После сортировки элементов счетчик оборотов образует шаблон «зубьев пилы».Векторизованный способ создания этого состоит в том, чтобы наблюдать, что разность зуба пилы имеет значения «скачка», где начинается новый зуб, а также везде.Так что это просто, чтобы построить.