计算numpy.chararray中字符出现次数的最快方法

时间:2018-09-03 07:39:03

标签: python-3.x numpy

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 :(得分:1)

chararray is deprectated, use array(..., dtype='<U1') instead。话虽这么说

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)

答案 1 :(得分:1)

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

  

注意:

     

存在chararray类是为了向后兼容   Numarray,不建议用于新开发。从...开始   numpy 1.4,如果需要字符串数组,建议使用   dtype object_,string_或unicode_的数组,并使用免费   numpy.char模块中的函数用于快速向量化的字符串   操作。

与常规数组一起,让我们提出两种方法。

方法1

在与搜索元素True比较之后,我们可以使用np.count_nonzero'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