Давайте рассмотрим некоторые варианты проблемы.Я не буду пытаться сделать строку такой же большой, как ваша.
In [393]: astr = 'ABCDEF'*10000
Сначала подсчитаем количество строк:
In [394]: astr.count('C')
Out[394]: 10000
In [395]: timeit astr.count('C')
70.2 µs ± 115 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Теперь попробуйте массив из 1 элемента с этой строкой:
In [396]: arr = np.array(astr)
In [397]: arr.shape
Out[397]: ()
In [398]: np.char.count(arr, 'C')
Out[398]: array(10000)
In [399]: timeit np.char.count(arr, 'C')
200 µs ± 2.97 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [400]: arr.dtype
Out[400]: dtype('<U60000')
Мой опыт использования char
заключается в том, что он выполняет итерации для элементов массива и применяет строковый метод.Так что это не может быть быстрее, чем применять метод string напрямую.Я полагаю, что в остальное время это какая-то непонятная накладная нагрузка.
Составьте список из строки - по одному символу на элемент списка:
In [402]: alist = list(astr)
In [403]: alist.count('C')
Out[403]: 10000
In [404]: timeit alist.count('C')
955 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Счетчик списка должен проходить по циклуэлементы, и сделайте тест против C
каждый раз.Тем не менее это быстрее, чем sum(i=='C' for i in alist)
(и варианты).
Теперь создайте массив из этого списка - односимвольные элементы:
In [405]: arr1 = np.array(alist)
In [406]: arr1.shape
Out[406]: (60000,)
In [407]: timeit arr1=='C'
634 µs ± 12.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [408]: timeit np.sum(arr1=='C')
740 µs ± 23.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
np.sum
относительно быстро.Больше всего времени занимает проверка на «С».
Если я построю числовой массив того же размера, время подсчета будет немного быстрее.Проверка на равенство с числом выполняется быстрее, чем проверка на эквивалентную строку.
In [431]: arr2 = np.resize(np.array([1,2,3,4,5,6]),arr1.shape[0])
In [432]: np.sum(arr2==3)
Out[432]: 10000
In [433]: timeit np.sum(arr2==3)
155 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
numpy
не обещает быть более быстрым для всех операций Python.В большинстве случаев при работе со строковыми элементами он сильно зависит от собственного строкового кода Python.