Вычисление «скользящей суммы отсчетов» в массиве NumPy - PullRequest
0 голосов
/ 11 октября 2018

У меня есть следующие массивы:

# input
In [77]: arr = np.array([23, 45, 23, 0, 12, 45, 45])

# result
In [78]: res = np.zeros_like(arr)

Теперь я хочу вычислить скользящую сумму уникальных элементов и сохранить ее в массиве res.

Конкретно, массив res должен быть:

In [79]: res
Out[79]: array([1, 1, 2, 1, 1, 2, 3])

[23, 45, 23, 0, 12, 45, 45]
[1, 1, 2, 1, 1, 2, 3]

Мы начинаем считать каждый элемент и увеличиваем count , если элемент появляется снова, пока не достигнем конца массива.Это значение должно быть возвращено в зависимости от конкретного элемента.


Как нам добиться этого с помощью встроенных функций NumPy?Я пытался использовать numpy.bincount, но это дает нежелательные результаты.

1 Ответ

0 голосов
/ 11 октября 2018

Не уверен, что вы найдете встроенную функцию, поэтому вот домашний напиток, использующий 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, потому что нам нужны индексы, чтобы в конце вернуться к исходному порядку.Здесь важно иметь стабильную сортировку, поэтому следует использовать медленную сортировку слиянием.

После сортировки элементов счетчик оборотов образует шаблон «зубьев пилы».Векторизованный способ создания этого состоит в том, чтобы наблюдать, что разность зуба пилы имеет значения «скачка», где начинается новый зуб, а также везде.Так что это просто, чтобы построить.

...