Вычисление «скользящей суммы отсчетов» для массива NumPy

1

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

# 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]

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


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

Теги:
numpy
counting

1 ответ

3
Лучший ответ

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

Как только элементы будут отсортированы, количество циклов будет составлять шаблон "пильный диск". Вексеризованный способ создания этого заключается в том, чтобы заметить, что разница между зубом пилы имеет "прыгающие" значения, где начинается новый зуб и что-то другое. Так что это просто вперед, чтобы построить.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню