NumPy布尔数组具有1位条目

54

在numpy中有没有一种方法可以创建一个每个条目只使用1位的布尔数组?

标准的np.bool类型是1字节,但这样我会使用8倍的内存。

在Google上我发现C++有std::vector<bool>


可以使用NumPy的本地函数来完成这个操作。 - Salvador Dali
3个回答

40

您可以使用numpy的packbitsunpackbits来实现此操作:

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

9
补充一下,我正在改进这个答案:https://github.com/numpy/numpy/pull/10855。目标是使packbits和unpackbits完全可逆,无需重新调整形状。 - Mad Physicist
2
@MadPhysicist 这将会很棒。感谢您的付出。完成后,请编写您自己的答案或编辑我的答案。 - Salvador Dali
2
@SalvadorDali 看起来这个 PR 已经合并到主分支了(https://github.com/numpy/numpy/commit/269d9855216e7c66708b1e2c6f5da7e5f39c70c1)。 - georges abitbol
3
唯一的问题在于,压缩数组意味着需要在内存中同时包含压缩和未压缩的数组,但有时您可能没有足够的内存来容纳更大的数组,这就是为什么您需要使用紧缩格式的原因。 - rizerphe
@SalvadorDali。在你提供帮助将近3年之后,我终于更新了你的答案,并加入了来自PR的信息 :) - Mad Physicist

23

您想要一个bitarray

高效的布尔数组 - C扩展

该模块提供了一种对象类型,可有效地表示布尔数组。 Bitarrays是序列类型,并且行为非常类似于通常的列表。八个位用一个字节在连续的内存块中表示。用户可以在两种表示之间选择; 小端和大端。所有功能都是用C实现的。提供了访问机器表示的方法。当需要对二进制文件进行位级访问时,例如便携式位图图像文件(.pbm),这可能非常有用。此外,在处理使用可变位长度编码的压缩数据时,您可能会发现此模块很有用...


谢谢!看起来非常有用,唯一缺少的是I/O例程将所有文件加载到内存中,而使用“numpy.load”我可以使用memorymap。 - Andrea Zonca
3
将这个位数组转回numpy数组容易吗?您能否添加一个小示例来演示一下呢? - KareemJ

15

你可能想要看一下 bitstring(文档在这里)。

如果从文件创建ConstBitArrayConstBitStream,则会使用mmap而不是将其加载到内存中。在这种情况下,它将无法进行更改,因此如果您想要进行更改,则必须将其加载到内存中。

例如,要在未加载到内存的情况下创建:

>>> a = bitstring.ConstBitArray(filename='your_file')
或者
>>> b = bitstring.ConstBitStream(a_file_object)

因为我只写一次,所以我不需要修改我的数据。 - Andrea Zonca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接