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

如何更快将大型压缩列结构时序数据加载到NumPy数组?

快速加载大型压缩列数据到NumPy数组的方案

核心矛盾拆解

你面临的问题本质是:NumPy数组的搜索性能最优,但npz格式加载速度远不如Parquet;而Parquet通过Pandas加载后转NumPy又存在额外延迟。需要找到兼顾Parquet级加载速度、压缩率,同时能直接映射到NumPy数组的解决方案。

针对性解决方案

1. 利用Parquet内存布局特性,避免全量转换

Pandas加载Parquet后,数值类型的列底层已经是NumPy数组,无需调用to_numpy()做全量复制。直接通过df[col].values或df[col].to_numpy(copy=False)获取原始数组引用,几乎无延迟:

import pandas as pd
from fasterparquet import ParquetFile

# 仅加载需要的列,进一步提速
pf = ParquetFile("your_data.parquet")
df = pf.to_pandas(columns=["timestamp", "value1", "value2"])

# 直接获取底层NumPy数组,无复制开销
timestamp_np = df["timestamp"].values
value1_np = df["value1"].to_numpy(copy=False)

这种方式既保留了Parquet的快速加载和高压缩率优势,又直接拿到NumPy数组的底层引用,完全规避转换延迟。

2. 用PyArrow直接读取Parquet到NumPy数组

PyArrow可以跳过Pandas,直接将Parquet列读取为Arrow数组,再零拷贝转换为NumPy数组(兼容数值类型):

import pyarrow.parquet as pq

# 读取指定列
table = pq.read_table("your_data.parquet", columns=["timestamp", "value1"])

# 零拷贝转换为NumPy数组
timestamp_np = table["timestamp"].to_numpy()
value1_np = table["value1"].to_numpy()

PyArrow的Parquet读取性能与fasterparquet相当,且转换到NumPy的开销极小,适合时序数据的列级读取场景。

3. 优化npz文件的存储与加载

如果必须使用NumPy原生格式,可通过以下方式提速:

  • 按列存储+按需加载:避免存储整个二维数组,加载时仅读取需要的列,减少解压量:
import numpy as np

# 假设data是shape=(10_000_000, 10)的时序数据数组
np.savez_compressed("data.npz", 
                    ts=data[:,0], val1=data[:,1], val2=data[:,2],
                    # 其他列...
                    val9=data[:,9])

# 加载时仅读取需要的列
with np.load("data.npz") as data:
    ts_np = data["ts"]
    val1_np = data["val1"]
  • 更换高效压缩算法:用Blosc替代np.savez_compressed默认的ZIP压缩,压缩/解压速度更快:
import blosc
import numpy as np

# 压缩单列时序数据
col_data = data[:,0]
compressed = blosc.compress(col_data, shuffle=blosc.SHUFFLE, cname='zstd')

# 保存到文件
with open("ts.blosc", "wb") as f:
    f.write(compressed)

# 加载时直接解压为NumPy数组
with open("ts.blosc", "rb") as f:
    compressed = f.read()
ts_np = np.frombuffer(blosc.decompress(compressed), dtype=col_data.dtype)

4. HDF5的内存映射优化

用h5py直接按列存储为HDF5数据集,加载时可通过内存映射直接访问数据,无需全量加载到内存:

import h5py

# 按列写入HDF5,启用gzip压缩
with h5py.File("data.h5", "w") as f:
    for i in range(data.shape[1]):
        f.create_dataset(f"col{i}", data=data[:,i], compression="gzip", compression_opts=9)

# 加载时直接获取NumPy数组(内存映射,延迟加载)
with h5py.File("data.h5", "r") as f:
    ts_np = f["col0"][:]  # 或直接用f["col0"]作为数组使用

适合超大规模时序数据的按需列加载场景。

方案对比总结

方案加载速度压缩率直接获取NumPy数组适用场景
Parquet + PyArrow极快高是(零拷贝)多数时序数据列级读取场景
Parquet + Pandas极快高是(无复制)需要同时使用Pandas和NumPy时
优化npz + Blosc较快中高是必须用NumPy原生格式的场景
HDF5 + h5py快高是(内存映射)超大规模数据按需加载列

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:33:21