4

我有一个由位串组成的 numpy 数组,我打算将位串转换为以 2 为基数的整数,以便执行一些异或位运算。我可以在python中将字符串转换为以2为底的整数:

int('000011000',2)

我想知道在numpy中是否有更快更好的方法来做到这一点。我正在研究的 numpy 数组的一个例子是这样的:

array([['0001'],
       ['0010']], 
      dtype='|S4')

我希望将其转换为:

array([[1],[2]])
4

2 回答 2

2

可以使用np.fromstring将每个字符串位分离为uint8类型数字,然后使用一些数学与矩阵乘法来转换/减少为十进制格式。因此,A作为输入数组,一种方法是这样的 -

# Convert each bit of input string to numerals
str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)

# Setup conversion array for binary number to decimal equivalent
de2bi_convarr = 2**np.arange(3,-1,-1)

# Use matrix multiplication for reducing each row of str2num to a single decimal
out = str2num.dot(de2bi_convarr)

样品运行 -

In [113]: A    # Modified to show more variety
Out[113]: 
array([['0001'],
       ['1001'],
       ['1100'],
       ['0010']], 
      dtype='|S4')

In [114]: str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)

In [115]: str2num
Out[115]: 
array([[0, 0, 0, 1],
       [1, 0, 0, 1],
       [1, 1, 0, 0],
       [0, 0, 1, 0]], dtype=uint8)

In [116]: de2bi_convarr = 2**np.arange(3,-1,-1)

In [117]: de2bi_convarr
Out[117]: array([8, 4, 2, 1])

In [118]: out = str2num.dot(de2bi_convarr)

In [119]: out
Out[119]: array([ 1,  9, 12,  2])

可以建议一种替代方法来避免np.fromstring. 使用这种方法,我们将在开始时转换为 int 数据类型,然后将每个数字分开,这应该等效str2num于前面的方法。其余代码将保持不变。因此,另一种实现方式是 -

# Convert to int array and thus convert each bit of input string to numerals
str2num = np.remainder(A.astype(np.int)//(10**np.arange(3,-1,-1)),10)

de2bi_convarr = 2**np.arange(3,-1,-1)
out = str2num.dot(de2bi_convarr)

运行时测试

让我们对迄今为止列出的所有解决问题的方法进行计时,包括@Kasramvd's loopy solution.

In [198]: # Setup a huge array of such strings
     ...: A = np.array([['0001'],['1001'],['1100'],['0010']],dtype='|S4')
     ...: A = A.repeat(10000,axis=0)


In [199]: def app1(A):             
     ...:     str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)
     ...:     de2bi_convarr = 2**np.arange(3,-1,-1)
     ...:     out = str2num.dot(de2bi_convarr)    
     ...:     return out
     ...: 
     ...: def app2(A):             
     ...:     str2num = np.remainder(A.astype(np.int)//(10**np.arange(3,-1,-1)),10)
     ...:     de2bi_convarr = 2**np.arange(3,-1,-1)
     ...:     out = str2num.dot(de2bi_convarr)    
     ...:     return out
     ...: 

In [200]: %timeit app1(A)
1000 loops, best of 3: 1.46 ms per loop

In [201]: %timeit app2(A)
10 loops, best of 3: 36.6 ms per loop

In [202]: %timeit np.array([[int(i[0], 2)] for i in A]) # @Kasramvd's solution
10 loops, best of 3: 61.6 ms per loop
于 2016-05-22T10:52:00.997 回答
0

由于KISS 原则,我想建议使用列表理解的以下方法:

>>> np.array([[int(i[0], 2)] for i in a])
array([[1],
       [2]])
于 2016-05-22T11:07:03.630 回答