20

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

4

4 回答 4

19

view你可以这样做unpackbits

输入:

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并根据您的需要应用建议。

于 2013-08-18T06:16:47.323 回答
16

这是我使用的解决方案:

def unpackbits(x, num_bits):
    if np.issubdtype(x.dtype, np.floating):
        raise ValueError("numpy data type needs to be int-like")
    xshape = list(x.shape)
    x = x.reshape([-1, 1])
    mask = 2**np.arange(num_bits, dtype=x.dtype).reshape([1, num_bits])
    return (x & mask).astype(bool).astype(int).reshape(xshape + [num_bits])

这是一个完全矢量化的解决方案,适用于任何维度的 ndarray,并且可以解压缩任何你想要的位。

于 2018-07-25T00:31:30.690 回答
3

我也没有找到任何函数,但也许使用 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,连接结果。或者,根据您的应用程序,使用结构化数组可能更方便。

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

于 2013-08-18T06:13:18.743 回答
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)
于 2018-03-02T16:16:02.633 回答