处理pandas DataFrame内存占用过高的问题,核心思路是优化数据类型和减少不必要的数据加载。下面是一些实用的代码方案:
1. 优化数据类型
import pandas as pd
import numpy as np
# 查看当前内存使用
df.info(memory_usage='deep')
# 自动优化所有数值列
def optimize_dtypes(df):
for col in df.select_dtypes(include=['int']).columns:
col_min = df[col].min()
col_max = df[col].max()
if col_min >= 0: # 无符号整数
if col_max < 255:
df[col] = df[col].astype(np.uint8)
elif col_max < 65535:
df[col] = df[col].astype(np.uint16)
elif col_max < 4294967295:
df[col] = df[col].astype(np.uint32)
else: # 有符号整数
if col_min > -128 and col_max < 127:
df[col] = df[col].astype(np.int8)
elif col_min > -32768 and col_max < 32767:
df[col] = df[col].astype(np.int16)
elif col_min > -2147483648 and col_max < 2147483647:
df[col] = df[col].astype(np.int32)
# 优化浮点数
for col in df.select_dtypes(include=['float']).columns:
df[col] = df[col].astype(np.float32)
# 优化字符串为分类类型
for col in df.select_dtypes(include=['object']).columns:
if df[col].nunique() / len(df) < 0.5: # 唯一值少于50%
df[col] = df[col].astype('category')
return df
df = optimize_dtypes(df)
2. 分块处理大数据
# 分块读取CSV
chunk_size = 100000
chunks = []
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# 处理每个分块
chunk = optimize_dtypes(chunk)
# 进行必要的过滤或聚合
processed_chunk = chunk[chunk['value'] > 0]
chunks.append(processed_chunk)
# 合并结果
df = pd.concat(chunks, ignore_index=True)
3. 使用更高效的数据格式
# 保存为parquet格式(压缩率高,读取快)
df.to_parquet('data.parquet', compression='snappy')
df = pd.read_parquet('data.parquet')
# 或者使用feather格式(内存映射)
df.to_feather('data.feather')
df = pd.read_feather('data.feather')
4. 及时删除不需要的数据
# 删除不需要的列
df = df.drop(columns=['unused_col1', 'unused_col2'])
# 删除重复行
df = df.drop_duplicates()
# 过滤不需要的行
df = df[df['important_col'].notna()]
# 强制垃圾回收
import gc
del large_object # 删除大对象
gc.collect() # 立即回收内存
5. 使用Dask处理超大数据
import dask.dataframe as dd
# 创建Dask DataFrame
ddf = dd.read_csv('huge_file.csv')
# 像pandas一样操作(惰性计算)
result = ddf[ddf['value'] > 100].groupby('category').mean()
# 需要结果时才计算
df_result = result.compute()
关键建议:优先优化数据类型,这是最有效的内存节省方法。