我有一个很大的二进制文件,需要将其转换为hdf5文件格式。
我正在使用Python3.6。我的想法是读入文件,对相关信息进行分类,将其解压缩并存储起来。我的信息以以下方式存储:8字节的时间紧随其后的是2字节的能量,然后是2字节的额外信息,然后是时间,……我目前的处理方式如下(我的信息读为一个字节数组,名称为byte_array):
for i in range(0, len(byte_array)+1, 12):
if i == 0:
timestamp_bytes = byte_array[i:i+8]
energy_bytes = byte_array[i+8:i+10]
extras_bytes = byte_array[i+10:i+12]
else:
timestamp_bytes += byte_array[i:i+8]
energy_bytes += byte_array[i+8:i+10]
extras_bytes += byte_array[i+10:i+12]
timestamp_array = np.ndarray((len(timestamp_bytes)//8,), '<Q',timestamp_bytes)
energy_array = np.ndarray((len(energy_bytes) // 2,), '<h', energy_bytes)
extras_array = np.ndarray((len(timestamp_bytes) // 8,), '<H', extras_bytes)
我认为有一个更快的方法可以执行此操作,也许可以避免遍历整个过程。我的文件最大为15GB,因此每一点改进都会有很大帮助。
答案 0 :(得分:1)
您应该能够告诉NumPy将数据解释为结构化数组并提取字段:
as_structured = numpy.ndarray(shape=(len(byte_array)//12,),
dtype='<Q, <h, <H',
buffer=byte_array)
timestamps = as_structured['f0']
energies = as_structured['f1']
extras = as_structured['f2']
这将产生由输入字节数组支持的三个数组。创建这些数组实际上应该是即时的,但是我不能保证与它们的合作会很快-我认为NumPy可能需要执行一些隐式复制来处理这些数组的对齐问题。可能(我不知道)是,首先使用.copy()
明确地自己复制它们可能会加快速度。
答案 1 :(得分:0)
您可以将numpy.frombuffer
与自定义数据类型一起使用:
import struct
import random
import numpy as np
data = [
(random.randint(0, 255**8), random.randint(0, 255*255), random.randint(0, 255*255))
for _ in range(20)
]
Bytes = b''.join(struct.pack('<Q2H', *row) for row in data)
dtype = np.dtype([('time', np.uint64),
('energy', np.uint16), # you may need to change that to `np.int16`, if energy can be negative
('extras', np.uint16)])
original = np.array(data, dtype=np.uint64)
result = np.frombuffer(Bytes, dtype)
print((result['time'] == original[:, 0]).all())
print((result['energy'] == original[:, 1]).all())
print((result['extras'] == original[:, 2]).all())
print(result)
示例输出:
True
True
True
[(6048800706604665320, 52635, 291) (8427097887613035313, 15520, 4976)
(3250665110135380002, 44078, 63748) (17867295175506485743, 53323, 293)
(7840430102298790024, 38161, 27601) (15927595121394361471, 47152, 40296)
(8882783920163363834, 3480, 46666) (15102082728995819558, 25348, 3492)
(14964201209703818097, 60557, 4445) (11285466269736808083, 64496, 52086)
(6776526382025956941, 63096, 57267) (5265981349217761773, 19503, 32500)
(16839331389597634577, 49067, 46000) (16893396755393998689, 31922, 14228)
(15428810261434211689, 32003, 61458) (5502680334984414629, 59013, 42330)
(6325789410021178213, 25515, 49850) (6328332306678721373, 59019, 64106)
(3222979511295721944, 26445, 37703) (4490370317582410310, 52413, 25364)]
答案 2 :(得分:0)
我不是numpy的专家,但这是我的5美分: 您有很多数据,可能不仅仅是RAM。 这指向了最简单的解决方案-不要尝试在程序中容纳所有数据。 当您将文件读取到变量中时-X GB被读取到RAM中。如果超过可用的RAM,则交换由您的OS完成。交换会减慢您的速度,因为不仅您有磁盘操作可从源文件读取,而且现在您还写入磁盘以将RAM内容转储到交换文件中。 代替编写脚本,以便脚本在必要时使用输入文件的某些部分(对于您而言,无论如何都应阅读文件,并且不要向后或向前跳)。
尝试以memory mapped data structure的形式打开输入文件(请注意Unix和Windows环境在用法上的差异)
然后,您可以一次执行简单的read([n])
个字节,并将其附加到数组中。
幕后的数据将被读取到RAM page by page as needed中,并且不会超出可用内存,也为阵列留下了更大的增长空间。
还要考虑这样一个事实,即结果数组也可能超出RAM,这将导致与读取大文件类似的速度降低。