Python使用Pandas处理大型数据集:如何解决内存不足问题
Pandas处理大型数据集的内存优化方案
一、读取CSV时的参数优化
- 指定数据类型:通过
dtype参数为列指定更紧凑的类型,避免默认的大内存类型。例如将重复率高的字符串列设为category,数值列用int8/float32替代int64/float64:
import pandas as pd dtype_config = { "product_type": "category", "user_age": "int8", "price": "float32" } df = pd.read_csv("large_dataset.csv", dtype=dtype_config)
- 只加载必要列:用
usecols参数指定需要处理的列,跳过无关数据:
df = pd.read_csv("large_dataset.csv", usecols=["user_id", "product_type", "price"])
- 逐块读取处理:设置
chunksize参数分批次加载数据,避免一次性占满内存:
chunk_iterator = pd.read_csv("large_dataset.csv", chunksize=100000) total_result = pd.DataFrame() for chunk in chunk_iterator: chunk_agg = chunk.groupby("product_type")["price"].mean() total_result = pd.concat([total_result, chunk_agg], axis=0) final_result = total_result.groupby(level=0).mean()
- 优化日期解析:用
parse_dates指定需解析的列,搭配infer_datetime_format=True加速解析;也可将日期转为Unix时间戳整数存储,减少内存占用:
df = pd.read_csv("large_dataset.csv", parse_dates=["order_time"], infer_datetime_format=True) # 或转成时间戳 df["order_timestamp"] = df["order_time"].astype("int64") // 10**9
- 关闭低内存检测:默认
low_memory=True会分块推断列类型,可能导致同一列类型混乱,统一指定类型后可设置low_memory=False避免额外内存开销。
二、读取后的内存压缩优化
- 自动降档数值类型:用
pd.to_numeric的downcast参数,将数值列压缩到最小可用类型:
df["user_age"] = pd.to_numeric(df["user_age"], downcast="integer") df["price"] = pd.to_numeric(df["price"], downcast="float")
- 字符串转分类类型:针对重复率高的字符串列,转为
category类型可大幅减少内存:
df["product_type"] = df["product_type"].astype("category")
- 稀疏类型处理缺失值:对缺失值占比极高的列,使用
SparseArray类型存储:
df["rare_col"] = pd.arrays.SparseArray(df["rare_col"])
三、操作环节的内存优化
- 优先原地操作:使用
inplace=True参数(如df.drop(columns=["unused_col"], inplace=True))避免生成新的DataFrame副本。 - 分组聚合精简输出:分组时用
as_index=False减少索引内存,仅指定需要的聚合函数,避免生成多余中间列:
agg_result = df.groupby("product_type", as_index=False).agg({"price": "mean", "user_id": "nunique"})
- 合并前精简数据:合并表前先过滤掉无关列,仅保留关联键和必要字段;无需排序时设置
merge的sort=False降低内存开销:
df1 = df1[["user_id", "age"]] df2 = df2[["user_id", "order_count"]] merged_df = pd.merge(df1, df2, on="user_id", sort=False)
- 转用高效存储格式:将CSV转为Parquet或Feather格式,这类列存储格式支持压缩和类型保留,读取时内存占用远低于CSV:
# 保存为Parquet df.to_parquet("optimized_data.parquet") # 读取Parquet df = pd.read_parquet("optimized_data.parquet")
四、进阶扩容方案
- 用Dask扩展处理能力:Dask API与Pandas兼容,可自动分块并行处理超出内存的数据集,无需大幅修改原有代码。
- 及时回收内存:处理过程中用
del删除不再使用的变量,再调用gc.collect()手动回收内存:
import gc del temp_df gc.collect()
内容的提问来源于stack exchange,提问作者Sitati
相关产品推荐
相关产品推荐

