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

如何在16GB内存设备加载8.3GB超大Pickle文件用于数据探索?

针对Pickle大数据集的采样解决方案

下面是几个无需增加内存的可行方案,适配你按列存储的数据集场景:

1. 流式逐对象读取,按需采样

Pickle是按序列化对象逐个写入的,不管存储形式是列还是行,都可以循环调用pickle.load()逐对象读取,中途控制采样比例:

  • 打开文件后,每次读取一个列对象
  • 对每个列直接截取10%的数据(比如取前10%或随机采样10%)
  • 累计读取到的总数据量达到目标后停止

示例代码:

import pickle
import os

file_path = "你的数据集文件.pkl"
total_file_size = os.path.getsize(file_path)
target_read_size = total_file_size * 0.1
current_read_size = 0
sampled_data = {}

with open(file_path, "rb") as f:
    while current_read_size < target_read_size:
        try:
            # 假设存储格式是(列名, 列数据)的键值对
            col_name, col_values = pickle.load(f)
            # 对单列采样10%,这里用简单的切片,也可以用随机采样
            sampled_data[col_name] = col_values[:int(len(col_values)*0.1)]
            # 更新已读取的字节数
            current_read_size = f.tell()
        except EOFError:
            break

# 转成DataFrame方便后续分析(如果需要)
import pandas as pd
sample_df = pd.DataFrame(sampled_data)

2. 用pickletools解析结构,精准截取对象边界

既然你已经用pickletools.dis()分析过样本,可以用它定位主文件中每个列对象的字节边界,然后只读取指定比例的列:

  • 先解析文件的opcode序列,统计总列数
  • 读取前10%的列对象,或者每个列截取部分数据

示例代码:

import pickletools
import pickle

file_path = "你的数据集文件.pkl"
total_cols = 0

# 先统计总共有多少列
with open(file_path, "rb") as f:
    while True:
        try:
            pickle.load(f)
            total_cols += 1
        except EOFError:
            break

target_cols = int(total_cols * 0.1)
sampled_data = {}

with open(file_path, "rb") as f:
    col_count = 0
    while col_count < target_cols:
        try:
            col_name, col_values = pickle.load(f)
            sampled_data[col_name] = col_values
            col_count += 1
        except EOFError:
            break

3. 转存为分块友好的格式(Parquet/Feather)

把Pickle转成Parquet这类支持分块读取的格式,后续采样会更方便:

  • 流式读取Pickle的列数据,分批次写入Parquet文件
  • 之后直接从Parquet中读取10%的样本

示例代码:

import pickle
import pandas as pd
import pyarrow.parquet as pq
import pyarrow as pa

file_path = "你的数据集文件.pkl"
chunk_size = 8  # 每次处理8列,可根据内存调整
current_chunk = []

with open(file_path, "rb") as f:
    while True:
        try:
            col_name, col_values = pickle.load(f)
            current_chunk.append((col_name, col_values))
            if len(current_chunk) == chunk_size:
                # 转成DataFrame并追加写入Parquet
                chunk_df = pd.DataFrame(dict(current_chunk))
                pq.write_to_dataset(
                    pa.Table.from_pandas(chunk_df),
                    root_path="转换后的数据集.parquet",
                    append=True
                )
                current_chunk = []
        except EOFError:
            # 处理剩余的列
            if current_chunk:
                chunk_df = pd.DataFrame(dict(current_chunk))
                pq.write_to_dataset(
                    pa.Table.from_pandas(chunk_df),
                    root_path="转换后的数据集.parquet",
                    append=True
                )
            break

# 读取10%的样本
full_table = pq.read_table("转换后的数据集.parquet")
sampled_table = full_table.sample(fraction=0.1)
sampled_df = sampled_table.to_pandas()

4. 内存映射文件辅助读取

用mmap把文件映射到虚拟内存,避免一次性加载全部数据,再逐对象读取采样:

import pickle
import mmap

file_path = "你的数据集文件.pkl"
sampled_data = {}
target_ratio = 0.1
total_objs = 0

# 先统计总对象数
with open(file_path, "rb") as f:
    while True:
        try:
            pickle.load(f)
            total_objs += 1
        except EOFError:
            break

target_objs = int(total_objs * target_ratio)

# 内存映射读取指定数量的对象
with open(file_path, "rb") as f:
    mm = mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)
    obj_count = 0
    while obj_count < target_objs:
        try:
            col_name, col_values = pickle.load(mm)
            sampled_data[col_name] = col_values
            obj_count += 1
        except EOFError:
            break
    mm.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:40:18