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

包含大型Pandas DataFrame的Python对象最优序列化方案

高效序列化含大型Pandas DataFrame的Python对象

Joblib:仍适用的高效选择

  • Joblib针对NumPy数组和Pandas对象做了专门优化,比标准pickle更高效——它会跳过Python对象层级的序列化,直接操作底层数值缓冲区,既提升速度又缩小文件体积。
  • 用法非常简便,直接传入你的MyWorld实例即可,无需额外处理DataFrame字段:
    from joblib import dump, load
    import pandas as pd
    from dataclasses import dataclass
    
    @dataclass
    class MyWorld:
        samples: pd.DataFrame
        addresses: pd.DataFrame
    
    # 生成测试用大型对象
    big_data = MyWorld(
        samples=pd.DataFrame({'col': range(1_000_000)}),
        addresses=pd.DataFrame({'addr': ['a']*1_000_000})
    )
    
    # 序列化(zstd压缩在速度和压缩比上平衡最优)
    dump(big_data, 'my_world.joblib', compress='zstd')
    # 反序列化
    loaded_data = load('my_world.joblib')
    
  • 压缩参数优先选zstd或lz4,比默认的gzip在速度和压缩效率上表现更好。

其他高效序列化工具

CloudPickle + 压缩

  • CloudPickle是pickle的扩展,支持序列化更多Python现代结构(比如dataclass),配合压缩工具可兼顾兼容性与效率:
    import cloudpickle
    import zstandard as zstd
    
    # 序列化
    with open('my_world.zst', 'wb') as f:
        compressor = zstd.ZstdCompressor()
        with compressor.stream_writer(f) as compressed_f:
            cloudpickle.dump(big_data, compressed_f)
    
    # 反序列化
    with open('my_world.zst', 'rb') as f:
        decompressor = zstd.ZstdDecompressor()
        with decompressor.stream_reader(f) as decompressed_f:
            loaded_data = cloudpickle.load(decompressed_f)
    
  • 这种方式兼容性极强,所有能运行Python的环境都能解析,压缩后的文件体积接近Parquet水平。

Dill

  • Dill同样是pickle的扩展,支持更多Python对象结构的序列化,配合压缩使用时,处理大型DataFrame的速度和文件体积都优于原生pickle,对dataclass的支持也很完善。

Pandas+Parquet半自动方案(比手动处理简便)

如果不想完全依赖pickle系工具,又不想逐个手动保存DataFrame,可以写一套通用函数,自动把dataclass里的DataFrame存为Parquet,其他字段用pickle:

import pandas as pd
import pickle
from dataclasses import fields

def save_my_world(obj: MyWorld, path: str):
    # 保存非DataFrame类型的字段
    meta = {f.name: getattr(obj, f.name) 
            for f in fields(obj) 
            if not isinstance(getattr(obj, f.name), pd.DataFrame)}
    with open(f"{path}_meta.pkl", 'wb') as f:
        pickle.dump(meta, f)
    # 自动将DataFrame保存为Parquet
    for f in fields(obj):
        val = getattr(obj, f.name)
        if isinstance(val, pd.DataFrame):
            val.to_parquet(f"{path}_{f.name}.parquet", compression='zstd')

def load_my_world(path: str) -> MyWorld:
    # 加载元数据
    with open(f"{path}_meta.pkl", 'rb') as f:
        meta = pickle.load(f)
    # 加载Parquet格式的DataFrame
    for f in fields(MyWorld):
        if f.name not in meta:
            meta[f.name] = pd.read_parquet(f"{path}_{f.name}.parquet")
    return MyWorld(**meta)

这套方案只需要写一次通用函数,后续无需手动处理每个DataFrame,Parquet的压缩率和读写速度都很出色,文件体积也是最小的。

方案对比

方案速度文件大小简便性兼容性
Joblib(带压缩)快较小极高好
CloudPickle+压缩中快较小高极好
Dill+压缩中快较小高好
Pandas+Parquet半自动快(读写)最小较高依赖Pandas

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:42:39