如何提取较大的数字Numpy数据类型的位

时间:2013-08-18 05:32:01

标签: python numpy

Numpy有一个库函数np.unpackbits,它会将uint8解压缩到长度为8的位向量中。是否有相应快速的方法来解压缩较大的数字类型?例如。 uint16uint32。我正在研究一个涉及数字之间频繁转换,数组索引和它们的位向量表示的问题,瓶颈是我们的打包和解包函数。

4 个答案:

答案 0 :(得分:10)

您可以使用viewunpackbits

执行此操作

输入:

unpackbits(arange(2, dtype=uint16).view(uint8))

输出:

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]

对于a = arange(int(1e6), dtype=uint16),这在我的机器上大约7毫秒非常快

%%timeit
unpackbits(a.view(uint8))

100 loops, best of 3: 7.03 ms per loop

至于字节顺序,您必须查看http://docs.scipy.org/doc/numpy/user/basics.byteswapping.html并根据您的需要在那里应用建议。

答案 1 :(得分:3)

这是我使用的解决方案:

def unpackbits(x,num_bits):
  xshape = list(x.shape)
  x = x.reshape([-1,1])
  to_and = 2**np.arange(num_bits).reshape([1,num_bits])
  return (x & to_and).astype(bool).astype(int).reshape(xshape + [num_bits])

这可与任何维ndarray一起使用,并且可以解压缩所需的许多位。它还不涉及任何循环。

答案 2 :(得分:2)

我也没有找到任何函数,但是使用Python的内置struct.unpack可以帮助使自定义函数比移动和更长的uint更快(注意我使用的是uint64)。

>>> import struct
>>> N = np.uint64(2 + 2**10 + 2**18 + 2**26)
>>> struct.unpack('>BBBBBBBB', N)
(2, 4, 4, 4, 0, 0, 0, 0)

想法是将它们转换为uint8,使用unpackbits,连接结果。或者,根据您的应用程序,使用structured arrays可能更方便。

还有内置的bin()函数,它产生0和1的字符串,但我不确定它有多快,也需要后处理。

答案 3 :(得分:0)

这适用于任意uint 的任意数组(即,对于多维数组以及大于uint8最大值的数字)

它循环遍历位数,而不是数组元素的数量,因此速度相当快。

def my_ManyParallel_uint2bits(in_intAr,Nbits):
    ''' convert (numpyarray of uint => array of Nbits bits) for many bits in parallel'''
    inSize_T= in_intAr.shape
    in_intAr_flat=in_intAr.flatten()
    out_NbitAr= numpy.zeros((len(in_intAr_flat),Nbits))
    for iBits in xrange(Nbits):
        out_NbitAr[:,iBits]= (in_intAr_flat>>iBits)&1
    out_NbitAr= out_NbitAr.reshape(inSize_T+(Nbits,))
    return out_NbitAr  

A=numpy.arange(256,261).astype('uint16')
# array([256, 257, 258, 259, 260], dtype=uint16)
B=my_ManyParallel_uint2bits(A,16).astype('uint16')
# array([[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
#       [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
#       [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
#       [1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
#       [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]], dtype=uint16)