самый быстрый способ подсчитать количество вхождений персонажа в numpy.chararray - PullRequest
0 голосов
/ 03 сентября 2018

Pythonists,

Какой самый быстрый способ подсчета вхождения символа в массиве numpy.character.

Я делаю следующее:

In [59]: for i in range(10):
...:     m = input("Enter A or B: ")
...:     rr[0][i] = m
...:     
Enter A or B: B
Enter A or B: B
Enter A or B: B
Enter A or B: A
Enter A or B: B
Enter A or B: A
Enter A or B: A
Enter A or B: A
Enter A or B: B
Enter A or B: A

In [60]: rr
Out[60]: 
chararray([['B', 'B', 'B', 'A', 'B', 'A', 'A', 'A', 'B', 'A']],
          dtype='<U1')

In [61]: %timeit a = rr.count('A')
12.5 µs ± 206 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [62]: %timeit d = len(a[a.nonzero()])
3.03 µs ± 54.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Я считаю, что должен быть лучший способ достичь этого со скоростью и элегантностью.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

It's better to stick to regular NumPy arrays over the chararrays:

Примечание:

Класс chararray существует для обратной совместимости с Numarray, не рекомендуется для новых разработок. Начиная с numpy 1.4, если нужны массивы строк, рекомендуется использовать массивы dtype object_, string_ или unicode_, и использовать свободный функции в модуле numpy.char для быстрой векторизованной строки операции.

Используя обычные массивы, давайте предложим два подхода.

Подход № 1

Мы могли бы использовать np.count_nonzero для подсчета единиц True после сравнения с поисковым элементом: 'A' -

np.count_nonzero(rr=='A')

Подход № 2

С chararray, содержащим только односимвольные элементы, мы могли бы намного лучше оптимизировать, просматривая его с помощью uint8 dtype, а затем сравнивая и подсчитывая. Подсчет будет намного быстрее, так как мы будем работать с числовыми данными. Реализация будет -

np.count_nonzero(rr.view(np.uint8)==ord('A'))

На Python 2.x это будет -

np.count_nonzero(np.array(rr.view(np.uint8))==ord('A'))

Задержка

Временные параметры исходных данных выборки и масштабированы до 10,000x масштабированы -

# Original sample data
In [10]: rr
Out[10]: array(['B', 'B', 'B', 'A', 'B', 'A', 'A', 'A', 'B', 'A'], dtype='<U1')

# @Nils Werner's soln
In [14]: %timeit np.sum(rr == 'A')
100000 loops, best of 3: 3.86 µs per loop

# Approach #1 from this post
In [13]: %timeit np.count_nonzero(rr=='A')
1000000 loops, best of 3: 1.04 µs per loop

# Approach #2 from this post
In [40]: %timeit np.count_nonzero(rr.view(np.uint8)==ord('A'))
1000000 loops, best of 3: 1.86 µs per loop

# Original sample data scaled by 10,000x
In [16]: rr = np.repeat(rr,10000)

# @Nils Werner's soln
In [18]: %timeit np.sum(rr == 'A')
1000 loops, best of 3: 734 µs per loop

# Approach #1 from this post
In [17]: %timeit np.count_nonzero(rr=='A')
1000 loops, best of 3: 659 µs per loop

# Approach #2 from this post
In [24]: %timeit np.count_nonzero(rr.view(np.uint8)==ord('A'))
10000 loops, best of 3: 40.2 µs per loop
0 голосов
/ 03 сентября 2018

chararray отменено, используйте array(..., dtype='<U1') вместо . Это, как говорится, вы можете сделать

r = np.array([['B', 'B', 'B', 'A', 'B', 'A', 'A', 'A', 'B', 'A']])

%timeit numpy.sum(r == 'A')
# 4.82 µs ± 126 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...