我可以从半结构化二进制数据中有效地创建pandas数据帧吗?

时间:2016-10-05 16:53:26

标签: python pandas numpy binary

我需要将大型二进制文件转换为n x 3个数组。数据是由(x,y,时间)坐标定义的一系列图像帧。每个帧使用两个32位整数来定义n x 3维,并使用n个三元组的16位整数来定义(x,y,时间)值。结果是二进制结构,如下所示:

int32, int32, uint16, uint16, uint16, ..., int32, int32, uint16, uint16, uint16,依此类推。

我的第一次尝试涉及将二进制数据转换为1D数组,然后将我想要的部分添加到数据框中。当前数据已经按照这样的方式排序,即可以在没有两个int32值的情况下重建帧分离,因此可以在必要时删除它们。如果不是这种情况,可以通过在将每个帧添加到最终数据帧之前单独排序来实现相同的效果。

import numpy as np
import pandas as pd

def frame_extract(index):
    n = data[index]
    subarray=data[index+4:index+(3*n+4)]
    subarray=np.reshape(subarray, (len(subarray)/3,3))
    frame = pd.DataFrame(data=subarray, columns=['x','y','t'])
    return frame

def indexer(index):
    n = data[index]
    new_index = index+(3*n+4)
    return new_index

data = np.fromfile('file.bin', dtype='<u2')
framedata = pd.DataFrame()

index = 0
while index <= len(data)-1:
    framedata = framedata.append(frame_extract(index), ignore_index=True)
    index = indexer(index)
print(framedata)

上面的工作,但是while循环非常慢,特别是与以下结构化方法相比,如果int32值不在路上,它将正常工作(并且数量级更快): / p>

dt = np.dtype([('x', '<u2'), ('y', '<u2'), ('time', '<u2')])
data = np.fromfile("file.bin", dtype=dt)
df = pd.DataFrame(data.tolist(), columns=data.dtype.names)

有没有更有效的方法来接近这个?如果是这样,在解压缩二进制数据时,或者在将二进制数据转换为整数之后,它会更容易吗?

我正在考虑使用生成器将二进制文件读取为一系列块(即使用两个32位整数来决定我需要的16位整数块的大小),但我是还不熟悉这些,以了解这是否是正确的方法。

2 个答案:

答案 0 :(得分:0)

每次附加到数据框时,都会将整个内容复制到内存中的新位置。您将需要使用具有完整最终大小的numpy数组初始化数据框,然后使用iloc()等将其编入索引,当您使用成像数据填充它时。

另外,您是否有使用pandas数据帧存储成像数据的具体原因?它们并不是真正意义上的......

答案 1 :(得分:0)

count参数通过允许np.fromfile利用int32值定义的结构来简化此操作。以下for循环分别创建每个图像框架:

f = open('file.bin', 'rb')
for i in np.arange(1,15001,1): 
    m, n = np.fromfile(f, dtype='<i', count=2)
    frame = np.reshape(np.fromfile(f, dtype='<u2', count=m*n), (m, n))

可以使用以下方法将每个帧添加到列表并转换为数据框:

f = open('file.bin', 'rb')
xyt_data = list()
for i in np.arange(1,15001,1):
    m, n = np.fromfile(f, dtype='<i', count=2)
    frame = np.reshape(np.fromfile(f, dtype='<u2', count=m*n), (m, n))
    xyt_data.append(frame)
df = pd.DataFrame(np.vstack(xyt_data), columns=['x','y','t'])

结果比原始问题中描述的版本快三个数量级。