我想将一个numpy数组写入二进制文件,但我想对整数使用非标准大小编码。例如,一些int数组将以3位整数写入文件,有些为7位,有些为13位......
我已经看到有一个numpy方法tofile()
它只适用于给定的数组dtypes,它们是int8,int16,int32等。(Reference)
如何将其写入具有可变位长的文件?
答案 0 :(得分:2)
我已经使用bitstring
模块为此编写了一个方法。
def int_array_to_bitstream(int_array, precision):
int_list = int_array.astype(int).tolist()
bits = ''
for integer in int_array:
bits += bitstring.BitStream(int=integer, length=precision)
return bits
它接受numpy数组的每个成员,并使用precision
位数将其转换为整数的二进制表示。这完全符合我的要求,但是使用起来很慢。
我正在寻找更快的方法来实现相同目标,无论是作为一个全新的方法,还是通过改进当前的方法
更新14.6。
尝试了另一个答案中的方法。
def int_array_to_bitstream_ver2(int_array, precision):
bits = bitstring.BitStream().join(bitstring.BitStream(uint=integer, length=precision) for integer in int_array)
return bits
速度差异很小。适用于int_array = arange(100000)
和precision = 24
。
int_array_to_bitstream -> 5.958 sec
int_array_to_bitstream_ver1 -> 5.614 sec
答案 1 :(得分:1)
给出一个具有bitstring的具体例子:
>>> from bitstring import Bits
>>> a = [3,1,2,6,4,10] # some unsigned integers to encode
>>> p = 5 # number of bits of precision to use
现在从每个整数创建5位位串并将它们连接在一起:
>>> b = Bits().join(Bits(uint=x, length=p) for x in a)
>>> b
Bits('0b000110001000001001100010001010')
可以转换为字节,但请注意,如果需要,它将填充零位到字节边界。写入文件时,您将始终拥有整数个字节,就像文件系统的工作方式一样:
>>> b.tobytes()
'\x18\x82b('
要再次解码它有很多选项,但由于所有内容都相同,cut
方法很有用:
>>> [x.uint for x in b.cut(p)]
[3, 2, 1, 6, 4, 10]
有关详细信息,请参阅the docs。就效率而言,纯Python应该是相当不错的。如果你真的需要更高的速度,那么尝试使用bitarray模块,它在C中实现,应该能够同样很好地处理这个问题。