numpy总和比字符串计数慢

时间:2019-04-22 15:32:23

标签: python string numpy count

我正在比较使用一个z_proto字符和一个字符串方法numpy array计算一个很长的字符串中有多少个字母'C'的性能。
基因组是一个很长的字符串。

count

我期望一个numpy数组会更快地对其进行计算,但是我错了。

有人可以向我解释count方法的工作原理,它比使用numpy数组更快?

谢谢!

1 个答案:

答案 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自己的字符串代码。