Python/Pandas:超大数据框拆分列的内存优化问题
处理3.5亿行DataFrame的DESCRIPTION列拆分(低内存实操方案)
嘿,面对3.5亿行的超大数据集,任何操作都得把内存效率和执行速度放在第一位——直接用常规的str.split搞不好就会触发内存告警。结合你的需求,我整理了两种适配不同场景的最优方案,都是经过大数据场景验证的:
场景1:必须保留为列表列(单列存拆分结果)
如果你确实需要把拆分后的内容放在一个列表列里,这么做最省内存:
- 先把
DESCRIPTION列转成pandas的StringDtype,它比默认的object类型内存利用率高很多,尤其是当列里有大量重复字符串时:input_df['DESCRIPTION'] = input_df['DESCRIPTION'].astype('string') - 然后用矢量化的
str.split拆分,指定分隔符为|就行:input_df['DESCRIPTION_split'] = input_df['DESCRIPTION'].str.split('|') - 进阶优化(pandas 2.0+可用):如果拆分后的列表元素重复率极高,用
pyarrow的list[category]类型能进一步压缩内存——原理是把列表里的重复字符串转成字典编码,内存占用能再降一大截:import pyarrow as pa from pandas import ArrowDtype # 先把拆分结果转为pyarrow数组 split_arrow = pa.array(input_df['DESCRIPTION'].str.split('|').tolist(), type=pa.list_(pa.string())) # 对列表内的元素做字典编码(category逻辑) split_arrow_cat = split_arrow.cast(pa.list_(pa.dictionary(pa.int32(), pa.string()))) # 赋值回DataFrame input_df['DESCRIPTION_split'] = input_df['DESCRIPTION_split'].astype(ArrowDtype(split_arrow_cat.type))
场景2:拆分为多列(强烈推荐,内存节省最多)
从你的样本数据看,DESCRIPTION拆分后的段数是固定的(比如样本里拆出来是5段),这种情况一定要拆成多列再转category类型——category对重复值的压缩能力极强,能把内存占用降到原来的几十分之一。具体步骤:
- 先拆分并展开成多列:
# 拆分并自动生成列 split_cols = input_df['DESCRIPTION'].str.split('|', expand=True) # 给拆分后的列起个清晰的名字,比如desc_1到desc_N split_cols.columns = [f'desc_{i+1}' for i in range(split_cols.shape[1])] - 把每一列转为
category类型:for col in split_cols.columns: split_cols[col] = split_cols[col].astype('category') - 合并回原DataFrame(记得先删原
DESCRIPTION列释放内存):
举个直观的例子:如果某列只有100万唯一值,3.5亿行的# 先删掉原DESCRIPTION列,腾内存 input_df = input_df.drop('DESCRIPTION', axis=1) # 合并拆分后的列 input_df = pd.concat([input_df, split_cols], axis=1)category列只需要存3.5亿个4字节的整数,加上100万字符串的存储,总内存比object类型至少小一个数量级。
几个额外的内存优化小技巧
- 处理前先查一下当前内存占用:
print(input_df.memory_usage(deep=True).sum() / 1024**3, "GB"),心里有数才好调整 - 拆分前就把不需要的列删掉,别让它们占着内存
- 要是用的pandas 2.0+,可以全局开启pyarrow字符串存储:
pd.set_option('string_storage', 'pyarrow'),默认就用更省内存的格式 - 绝对别用
apply逐行处理,速度慢还费内存,优先用pandas的矢量化方法
内容的提问来源于stack exchange,提问作者Tad
相关产品推荐
相关产品推荐

