打包布尔数组需要遍历int(numpy 1.8.2)

2024-09-29 19:20:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我在寻找更简洁的方法来存储布尔值。 numpy内部需要8位来存储一个布尔值,但是np.packbits允许打包 他们,太酷了。在

问题是,要将一个4e6 bytes数组a32e6 bytes封装在布尔数组中,我们首先需要花费256e6字节来转换int数组中的布尔数组!在

In [1]: db_bool = np.array(np.random.randint(2, size=(int(2e6), 16)), dtype=bool)
In [2]: db_int = np.asarray(db_bool, dtype=int)
In [3]: db_packed = np.packbits(db_int, axis=0)
In [4]: db.nbytes, db_int.nbytes, db_packed.nbytes
Out[5]: (32000000, 256000000, 4000000)

有一个一年前的问题在纽比追踪器中被打开了。 https://github.com/numpy/numpy/issues/5377

有人有解决方案/更好的解决办法吗?在

当我们试图以正确的方式进行追踪时:

^{pr2}$

PS:我会尝试一下bitarray,但会在纯numpy中获得它。在


Tags: 方法innumpydbbytesnp数组int
2条回答
<>昨天,我回答了一个新问题,关于如何处理Python中的位——与C++相比。在警告不会有速度提升之后,我使用Python内部的bytearray对象绘制了一个简单的“bitarray”。在

这一点也不快,但是如果您不再对数组位进行操作,而只需要输出,也许就足够了,因为您可以完全控制Python代码中的转换。否则,您可以尝试只提示静态类型并运行与Cython相同的代码,您可能希望使用dtype=int8的np数组而不是bytearray:

class BitArray(object):
    def __init__(self, length):
        self.values = bytearray(b"\x00" * (length // 8 + (1 if length % 8  else 0)))
        self.length = length

    def __setitem__(self, index, value):
        value = int(bool(value)) << (7 - index % 8)
        mask = 0xff ^ (7 - index % 8)
        self.values[index // 8] &= mask
        self.values[index // 8] |= value
    def __getitem__(self, index):
        mask = 1 << (7 - index % 8)
        return bool(self.values[index // 8] & mask)

    def __len__(self):
        return self.length

    def __repr__(self):
        return "<{}>".format(", ".join("{:d}".format(value) for value in self))

此代码最初发布在此处:Is there a builtin bitset in Python that's similar to the std::bitset from C++?

不需要将布尔数组转换为本机的int数据类型(x86趶64上为64位)。可以通过将布尔数组视为np.uint8来避免复制布尔数组,它也为每个元素使用一个字节:

packed = np.packbits(db_bool.view(np.uint8))

unpacked = np.unpackbits(packed)[:db_bool.size].reshape(db_bool.shape).view(np.bool)

print(np.all(db_bool == unpacked))
# True

另外,np.packbits现在应该可以直接在布尔数组上工作,从一年前的this commit开始(numpyv1.10.0及更新版本)。在

相关问题 更多 >

    热门问题