2016-12-09 70 views
4

是否有将二进制(0 | 1)numpy数组转换为整数或二进制字符串的快捷方式? F.e.将二进制(0 | 1)numpy转换为整数或二进制串?

b = np.array([0,0,0,0,0,1,0,1]) 
    => b is 5 

np.packbits(b) 

工作,但只适用于8位值..如果numpy是9个或更多的元素,它会生成2个或更多的8位值。 另一种选择是返回的0串| 1 ...

我目前做的是:

ba = bitarray() 
    ba.pack(b.astype(np.bool).tostring()) 
    #convert from bitarray 0|1 to integer 
    result = int(ba.to01(), 2) 

这是丑陋的!

回答

5

的一种方法是使用dot-product2-powered范围阵列 -

b.dot(2**np.arange(b.size)[::-1]) 

采样运行 -

In [95]: b = np.array([1,0,1,0,0,0,0,0,1,0,1]) 

In [96]: b.dot(2**np.arange(b.size)[::-1]) 
Out[96]: 1285 

或者,我们可以使用按位左移运算符来创建范围阵列,从而得到所需的输出像这样 -

b.dot(1 << np.arange(b.size)[::-1]) 

如果定时感兴趣 -

In [148]: b = np.random.randint(0,2,(50)) 

In [149]: %timeit b.dot(2**np.arange(b.size)[::-1]) 
100000 loops, best of 3: 13.1 µs per loop 

In [150]: %timeit b.dot(1 << np.arange(b.size)[::-1]) 
100000 loops, best of 3: 7.92 µs per loop 

逆过程

要检索回二进制数组,使用np.binary_repr非常久远np.fromstring -

In [96]: b = np.array([1,0,1,0,0,0,0,0,1,0,1]) 

In [97]: num = b.dot(2**np.arange(b.size)[::-1]) # integer 

In [98]: np.fromstring(np.binary_repr(num), dtype='S1').astype(int) 
Out[98]: array([1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]) 
+0

聪明:)如果有人能想出更好的办法......在我批准之前,将等待一两天。 – user1019129

+0

任何建议转换回原来的二进制数组格式? – Jonathan

+0

@Jonathan好问题!应该早些加入。发布。 – Divakar

0
def binary_converter(arr): 
    total = 0 
    for index, val in enumerate(reversed(arr)): 
     total += (val * 2**index) 
    print total 


In [14]: b = np.array([1,0,1,0,0,0,0,0,1,0,1]) 
In [15]: binary_converter(b) 
1285 
In [9]: b = np.array([0,0,0,0,0,1,0,1]) 
In [10]: binary_converter(b) 
5 

b = np.array([1,0,1,0,0,0,0,0,1,0,1]) 
sum(val * 2**index for index, val in enumerate(reversed(b))) 
0

使用numpy进行转换可将您限制为64位带符号的二进制结果。如果你真的想使用numpy的和64位的限制适用于您使用numpy的更快的实现是:

import numpy as np 
def bin2int(bits): 
    return np.right_shift(np.packbits(bits, -1), bits.size).squeeze() 

因为通常如果你正在使用numpy的你关心的速度,然后为> 64位最快的实现结果是:

import gmpy2 
def bin2int(bits): 
    return gmpy2.pack(list(bits[::-1]), 1) 

如果你不想抢依赖于gmpy2这是一个慢一点,但没有依赖关系,并支持> 64位的结果:

def bin2int(bits): 
    total = 0 
    for shift, j in enumerate(bits[::-1]): 
     if j: 
      total += 1 << shift 
    return total 

邻bservant会注意到在最后一个版本中的一些相似之处,这个问题的其他答案主要区别在于使用了代替**的< <运算符,在我的测试中,这导致了速度的显着提高。

相关问题