You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在转换为numpy数组/pandas DataFrame前高效过滤字节流?

问题描述

我需要在将数据转换为NumPy数组或Pandas DataFrame前,高效过滤掉不需要的字段。数据是以单个字符串缓冲区(每条记录对应一个缓冲区)传递给程序的,目前我用np.frombuffer在收集所有记录后构建数组。

问题在于单条记录可能包含数千个字段,但有时我只需要其中一小部分:

  • 如果先拼接所有记录再构建完整数组,再提取需要的列,会浪费大量内存;
  • 如果逐条切片记录再重新拼接,中间步骤又会让过滤比直接读取全部数据更慢。

当前无过滤流程

# 假设此处有函数逐条获取记录并添加到'data'中
data = [b'\x00\x00\x00\x00\x00\x00\xf0?one     \x00\x00\x00\x00\x00\x00Y@',
        b'\x00\x00\x00\x00\x00\x00\x00@two     \x00\x00\x00\x00\x00\x00i@',
        b'\x00\x00\x00\x00\x00\x00\x08@three   \x00\x00\x00\x00\x00\xc0r@',
        b'\x00\x00\x00\x00\x00\x00\x10@four    \x00\x00\x00\x00\x00\x00y@']

final_data = b''.join(data)

arr = np.frombuffer(final_data, dtype=struct_dtypes)
df = pd.DataFrame(arr)

# 生成的DataFrame
    n1     ch     n2
0  1.0    one  100.0
1  2.0    two  200.0
2  3.0  three  300.0
3  4.0   four  400.0

当前低效过滤方案

final_data = b''.join(b''.join(buffer[offset: offset + 8] for offset in [0, 16]) for buffer in data)

struct_dtypes = np.dtype([('n1', 'd'), ('n2', 'd')])
arr = np.frombuffer(final_data, dtype=struct_dtypes)
df = pd.DataFrame(arr)

# 生成的DataFrame
    n1     n2
0  1.0  100.0
1  2.0  200.0
2  3.0  300.0
3  4.0  400.0

这种逐条切片再拼接的方式效率很低,请问有没有合适的方法可以只读取字符串缓冲区中需要的部分?


解决方案

直接通过自定义NumPy dtype的offsets和itemsize参数,让np.frombuffer直接跳过不需要的字段,无需提前切片或拼接数据:

实现代码

# 定义只包含需要字段的dtype,指定每个字段的偏移量和单条记录总长度
struct_dtypes = np.dtype({
    'names': ['n1', 'ch'],
    'formats': ['d', '8V'],  # '8V'表示8字节的原始数据(对应示例中的字符串字段)
    'offsets': [0, 8],       # 每个字段在单条记录中的起始偏移
    'itemsize': 24           # 单条记录的总字节长度(对应原始每条buffer的长度)
})

final_data = b''.join(data)
arr = np.frombuffer(final_data, dtype=struct_dtypes)

核心原理

  • 指定字段偏移:通过offsets参数定义需要读取的字段在单条记录中的起始字节位置,NumPy会直接定位读取,自动跳过不需要的字段;
  • 固定记录长度:itemsize参数设置单条记录的总字节数,确保np.frombuffer能正确将连续的二进制数据分割为独立记录;
  • 零数据修改:无需对原始二进制缓冲区做切片、拼接操作,直接基于完整二进制数据按需读取,最大化内存利用率和处理速度。

使用已采纳方案后的更新

struct_dtypes = np.dtype({'names': ['n1', 'ch'],
                          'formats': ['d', '8V'],
                          'offsets': [0, 8],
                          'itemsize': 24})

final_data = b''.join(data)

arr = np.frombuffer(final_data, dtype=struct_dtypes)

内容的提问来源于stack exchange,提问作者StevenS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:24:26