具有1位条目的numpy布尔数组
有没有办法在numpy中创建一个布尔值数组,每个元素只用1个比特位?
标准的np.bool
类型占用1个字节,但这样我就用了8倍的内存。
我在谷歌上发现C++有一个叫做std::vector<bool>
的东西。
3 个回答
24
你想要一个bitarray:
高效的布尔数组 - C扩展
这个模块提供了一种对象类型,可以高效地表示布尔值的数组。bitarray就像普通的列表一样,是一种序列类型。八个比特(bit)会被一个字节(byte)连续存储在内存中。用户可以选择两种表示方式:小端(little-endian)和大端(big-endian)。所有功能都是用C语言实现的。这个模块还提供了访问机器表示的方法。当你需要对二进制文件进行比特级别的访问时,比如可移植位图图像文件(.pbm),这个模块会很有用。此外,当处理使用可变比特长度编码的压缩数据时,你也可能会发现这个模块很实用...
41
要实现这个功能,你可以使用numpy库里的packbits
和unpackbits
这两个函数。
import numpy as np
# original boolean array
A1 = np.array([
[0, 1, 1, 0, 1],
[0, 0, 1, 1, 1],
[1, 1, 1, 1, 1],
], dtype=bool)
# packed data
A2 = np.packbits(A1, axis=None)
# checking the size
print(len(A1.tostring())) # 15 bytes
print(len(A2.tostring())) # 2 bytes (ceil(15/8))
# reconstructing from packed data. You need to resize and reshape
A3 = np.unpackbits(A2, count=A1.size).reshape(A1.shape).view(bool)
# and the arrays are equal
print(np.array_equal(A1, A3)) # True
在numpy 1.17.0之前,第一个函数使用起来很简单,但要把数据恢复成原来的样子就需要做一些额外的处理。下面是一个例子:
import numpy as np
# original boolean array
A1 = np.array([
[0, 1, 1, 0, 1],
[0, 0, 1, 1, 1],
[1, 1, 1, 1, 1],
], dtype=np.bool)
# packed data
A2 = np.packbits(A1, axis=None)
# checking the size
print(len(A1.tostring())) # 15 bytes
print(len(A2.tostring())) # 2 bytes (ceil(15/8))
# reconstructing from packed data. You need to resize and reshape
A3 = np.unpackbits(A2, axis=None)[:A1.size].reshape(A1.shape).astype(np.bool)
# and the arrays are equal
print(np.array_equal(A1, A3)) # True