我正在比较使用一个z_proto
字符和一个字符串方法numpy array
计算一个很长的字符串中有多少个字母'C'的性能。
基因组是一个很长的字符串。
count
我期望一个numpy数组会更快地对其进行计算,但是我错了。
有人可以向我解释count方法的工作原理,它比使用numpy数组更快?
谢谢!
答案 0 :(得分:2)
让我们探讨这个问题的一些变化。我不会尝试使用与您一样大的字符串。
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方法。因此,它不可能比直接应用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
相对较快。花费最多的时间是对“ C”的检查。
如果我构造相同大小的数字数组,则计数时间要快得多。对数字的相等性测试比对等的字符串测试要快。
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自己的字符串代码。