将位串 numpy 数组转换为整数基数 2 的最快方法
fastest way to convert bitstring numpy array to integer base 2
我有一个由位串组成的 numpy 数组,我打算将位串转换为以 2 为底的整数,以便执行一些异或按位运算。我可以在 python 中将字符串转换为基数为 2 的整数:
int('000011000',2)
我想知道在 numpy 中是否有更快更好的方法来做到这一点。我正在处理的 numpy 数组的一个例子是这样的:
array([['0001'],
['0010']],
dtype='|S4')
我希望将其转换为:
array([[1],[2]])
可以使用 np.fromstring
将每个字符串位分离成 uint8
类型的数字,然后使用一些 maths 与矩阵乘法 convert/reduce转十进制格式。因此,以 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)
运行时测试
让我们计算一下到目前为止列出的所有解决问题的方法,包括 。
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
由于 KISS principle,我想建议使用列表理解的以下方法:
>>> np.array([[int(i[0], 2)] for i in a])
array([[1],
[2]])
我有一个由位串组成的 numpy 数组,我打算将位串转换为以 2 为底的整数,以便执行一些异或按位运算。我可以在 python 中将字符串转换为基数为 2 的整数:
int('000011000',2)
我想知道在 numpy 中是否有更快更好的方法来做到这一点。我正在处理的 numpy 数组的一个例子是这样的:
array([['0001'],
['0010']],
dtype='|S4')
我希望将其转换为:
array([[1],[2]])
可以使用 np.fromstring
将每个字符串位分离成 uint8
类型的数字,然后使用一些 maths 与矩阵乘法 convert/reduce转十进制格式。因此,以 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)
运行时测试
让我们计算一下到目前为止列出的所有解决问题的方法,包括
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
由于 KISS principle,我想建议使用列表理解的以下方法:
>>> np.array([[int(i[0], 2)] for i in a])
array([[1],
[2]])