如何在DataFrame指定列统计多单词行且避免pd.Series内存分配
避免额外内存开销统计DataFrame指定列的多单词行数
需求与问题
需要统计DataFrame指定列中包含多个单词(以空格分隔)的行数,但原实现会额外分配pd.Series内存,导致内存占用上升,需优化。
原示例代码(存在内存问题)
source_pos = get_list_index_or_none(col_list, SOURCE_COLUMN) # 该行会复制列数据并分配额外内存,非最优实现 source_only = filtered_df.iloc[:, source_pos:source_pos + 1:].iloc[:, 0] rows_with_many_words_in_source = source_only.astype(str).str.count( ' ') + 1 > SOURCE_WORDS_LIMIT
内存使用对比
执行前内存状态
2022-07-29 12:27:56,974 - DEBUG - Total memory usage: 102.21875 MB 2022-07-29 12:27:57,539 - DEBUG - Total objects allocated: 438113 types | # objects | total size ======================================= | =========== | ============ pandas.core.frame.DataFrame | 2 | 24.61 MB str | 144600 | 23.60 MB dict | 40957 | 15.36 MB code | 36800 | 6.26 MB type | 5342 | 4.92 MB list | 31955 | 3.04 MB tuple | 34692 | 2.01 MB set | 2222 | 1.42 MB numpy.ndarray | 86 | 752.26 KB weakref | 9220 | 648.28 KB collections.OrderedDict | 269 | 459.09 KB abc.ABCMeta | 421 | 453.01 KB openpyxl.descriptors.MetaSerialisable | 424 | 440.56 KB int | 14551 | 426.82 KB builtin_function_or_method | 5516 | 387.84 KB
执行后内存状态
2022-07-29 12:28:10,295 - DEBUG - Total memory usage: 111.296875 MB 2022-07-29 12:28:10,793 - DEBUG - Total objects allocated: 439022 types | # objects | total size ======================================= | =========== | ============ pandas.core.series.Series | 48 | 24.93 MB pandas.core.frame.DataFrame | 2 | 24.61 MB str | 144605 | 23.60 MB dict | 41326 | 15.42 MB code | 36800 | 6.26 MB type | 5342 | 4.92 MB list | 31998 | 3.04 MB tuple | 34785 | 2.02 MB set | 2223 | 1.42 MB numpy.ndarray | 133 | 757.03 KB weakref | 9269 | 651.73 KB collections.OrderedDict | 269 | 459.09 KB abc.ABCMeta | 421 | 453.01 KB openpyxl.descriptors.MetaSerialisable | 424 | 440.56 KB int | 14597 | 428.08 KB
优化方案
核心思路
直接对原DataFrame的目标列进行链式操作,避免创建并持有中间Series变量;同时简化列索引方式,减少不必要的DataFrame切片复制。
优化后代码
source_pos = get_list_index_or_none(col_list, SOURCE_COLUMN) # 直接链式操作目标列,无中间变量,临时对象会被自动回收 rows_with_many_words_in_source = filtered_df.iloc[:, source_pos].astype(str).str.count(' ') + 1 > SOURCE_WORDS_LIMIT # 统计符合条件的行数 target_count = rows_with_many_words_in_source.sum()
优化细节说明
- 省略中间变量:原代码中
source_only变量会长期持有复制出的Series,导致内存无法释放。优化后直接链式调用,中间生成的临时Series在操作完成后会被垃圾回收,不会持续占用内存。 - 简化列索引:原代码用
iloc[:, source_pos:source_pos + 1]切片生成单列表格再取列,会额外创建DataFrame对象;直接用iloc[:, source_pos]可直接获取目标列的引用,避免不必要的复制。 - 可选优化:若目标列本身已是字符串类型,可省略
.astype(str)步骤,进一步减少内存操作。
内容的提问来源于stack exchange,提问作者comonadd
相关产品推荐
相关产品推荐

