我正在寻找更紧凑的方式来存储布尔值.numpy内部需要8位来存储一个布尔值,但np.packbits
允许打包它们,这很酷.
问题是要在4e6字节数组中包含一个32e6字节的布尔数组,我们需要先花费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)
numpy跟踪器中有一个关于该问题的问题已经打开了一年(参见 https://github.com/numpy/numpy/issues/5377)
有人有解决方案/更好的解决方法吗?
当我们尝试以正确的方式执行时的追溯:
In [28]: db_pb = np.packbits(db_bool) --------------------------------------------------------------------------- TypeError Traceback (most recent call last)in () ----> 1 db_pb = np.packbits(db_bool) TypeError: Expected an input array of integer data type In [29]:
PS:我会试试bitarray但是会把它变成纯粹的numpy.
无需将布尔数组转换为本机int
dtype(在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
现在应该直接在布尔数组作为工作的这个承诺从一年前(numpy的v1.10.0更新版本).