文章目录

Python Pandas处理千万级数据帧的内存优化技巧

发布于 2026-04-09 12:24:29 · 浏览 3 次 · 评论 0 条

Python Pandas处理千万级数据帧的内存优化技巧

处理千万级数据时,Pandas 经常会爆出 MemoryError,或者导致电脑卡死。这是因为 Pandas 默认加载方式非常“铺张”。通过优化数据类型和加载策略,通常能将内存占用降低 50% 甚至 90% 以下。


第一阶段:诊断内存占用情况

运行 以下代码查看数据帧的详细内存使用情况。

import pandas as pd

# 假设 df 是你的数据帧
df.info(memory_usage='deep')

重点关注输出信息中的 memory usage 列以及每一列的 Dtype(数据类型)。如果很多列显示为 objectint64/float64,这就是内存被浪费的根源。

查看 各列具体的内存占用统计,找出占用最大的几列。

df.memory_usage(deep=True).sort_values(ascending=False)

第二阶段:优化数值类型

Pandas 加载整数时默认使用 int64(64位),浮点数默认使用 float64。对于大多数业务数据,这完全没必要。

自动降级 数值列的最小类型。

# 处理整数列
df_int = df.select_dtypes(include=['int64'])
converted_int = df_int.apply(pd.to_numeric, downcast='integer')

# 处理浮点数列
df_float = df.select_dtypes(include=['float64'])
converted_float = df_float.apply(pd.to_numeric, downcast='float')

更新 原始数据帧。

df[converted_int.columns] = converted_int
df[converted_float.columns] = converted_float

执行 完上述步骤后,数值列通常会从 8 字节(int64/float64)降至 1 到 4 字节(int8float32),直接节省约 75% 的内存空间。


第三阶段:优化字符串与分类数据

字符串类型(object)是内存杀手。如果某列表示的是“性别”、“省份”、“产品ID”等重复度高的数据,将其转换为 category 类型是最高效的手段。

判断 某一列是否适合转换。经验法则是:当唯一值的数量除以总行数小于 0.5(即重复率高)时,转换效果显著。

检查 唯一值占比。

# 检查 'city' 列的唯一值比例
ratio = len(df['city'].unique()) / len(df)
print(ratio)

转换 低基数字符串列为 category 类型。

df['city'] = df['city'].astype('category')

对于纯文本内容(如用户评论、描述)无法转换为 category保持object 类型,但确保在后续处理中尽早丢弃不需要的文本列。


第四阶段:优化日期时间类型

日期通常以字符串(object)形式读入,既占内存又无法进行时间运算。

转换 日期字符串为 datetime 类型。

df['date_column'] = pd.to_datetime(df['date_column'])

datetime64[ns] 通常比存储日期的字符串更节省空间,且支持快速的时间序列操作。


第五阶段:读取时即优化

最好的优化是在数据进入内存之前就完成。与其读入后再转换,不如在 read_csv 时直接指定类型。

创建 一个字典,映射列名与目标类型。

dtype_dict = {
    'id': 'int32',
    'age': 'int8',
    'price': 'float32',
    'gender': 'category',
    'city': 'category'
}

使用 dtype 参数读取 CSV。

df = pd.read_csv('large_file.csv', dtype=dtype_dict)

指定 parse_dates 参数直接解析日期。

df = pd.read_csv('large_file.csv', dtype=dtype_dict, parse_dates=['date_column'])

第六阶段:分块处理超大文件

如果优化后仍然内存不足,使用 分块读取策略。不要一次性加载整个文件。

设置 chunksize 参数进行迭代读取。

chunk_size = 100000  # 每次读取 10 万行
chunk_iterator = pd.read_csv('huge_file.csv', chunksize=chunk_size)

for chunk in chunk_iterator:
    # 在这里对每一个 chunk 进行处理
    # 例如:过滤、聚合、清洗或保存到数据库
    process(chunk)

这种方式将内存占用维持在 chunk_size 对应的大小,无论文件总行数是多少,内存始终是稳定的。


第七阶段:及时释放无用内存

在数据清洗过程中,经常会产生中间变量。

使用 del 语句删除不再需要的大变量。

temp_df = pd.DataFrame(...)
# 处理完毕
del temp_df

手动调用 垃圾回收。

import gc
gc.collect()

常见数据类型内存占用对比表

了解不同类型的底层成本,有助于做出正确选择。

数据类型 说明 每个元素占用字节数 适用场景
int64 默认整数 8 极大数值(超出 20 亿)
int32 中等整数 4 一般 ID、计数(约 ±21 亿内)
int16 短整数 2 年龄、年份、评分(-32768 到 32767)
int8 极短整数 1 标志位(0-255)、状态码
float64 默认浮点数 8 高精度科学计算
float32 单精度浮点数 4 一般金额、经纬度、百分比
object 字符串/混合类型 变大 (通常 >50) 纯文本、JSON
category 分类数据 变小 (取决于基数) 重复的字符串(如性别、国家)
datetime64[ns] 时间戳 8 时间序列分析

记住:将 int64 改为 int8 能节省 87.5% 的该列内存;将字符串改为 category 在低基数情况下通常能节省 90% 以上。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文