如何高效移除DataFrame重复自定义索引行并保留指定列最大值行?
高效处理超大规模DataFrame:保留重复索引下b列最大值的行
针对你提到的数千张各含1.2亿行的DataFrame场景,核心要解决内存占用和处理速度的问题,以下是几种经过验证的高效方案:
一、单表处理方案
1. 单表无法全量载入内存:分块处理
如果单张表的大小超过内存容量,用分块读取+逐块处理的方式,避免内存溢出:
import pandas as pd def process_chunk(chunk): # 先按索引升序、b列降序排序,确保每个索引下b最大的行排在最前 chunk_sorted = chunk.sort_values(by=[chunk.index.name, 'b'], ascending=[True, False]) # 去重:保留每个索引的第一行(即b最大的行) return chunk_sorted[~chunk_sorted.index.duplicated(keep='first')] # 分块读取数据(假设数据存储为CSV,根据内存调整chunk_size) chunk_size = 10_000_000 # 1千万行/块,可按需调整 processed_chunks = [] for chunk in pd.read_csv('your_data.csv', index_col=0, chunksize=chunk_size): processed_chunks.append(process_chunk(chunk)) # 合并所有块后再次去重(跨块可能存在相同索引) final_df = pd.concat(processed_chunks) final_df = final_df.sort_values(by=[final_df.index.name, 'b'], ascending=[True, False]) final_df = final_df[~final_df.index.duplicated(keep='first')]
2. 单表可全量载入内存:排序后去重
这种方式比groupby.idxmax更高效,因为排序是pandas底层优化的操作,内存开销更低:
# 按索引升序、b列降序排序 df_sorted = df.sort_values(by=[df.index.name, 'b'], ascending=[True, False]) # 保留每个索引的第一行 final_df = df_sorted[~df_sorted.index.duplicated(keep='first')] # 简化写法:先按b降序排序,再按索引去重 df_sorted = df.sort_values(by='b', ascending=False) final_df = df_sorted.drop_duplicates(subset=df.index.name, keep='first')
二、多表批量处理优化
面对数千张表的场景,用并行计算框架提升效率:
用Dask处理超大规模数据集
Dask天生支持分块和并行计算,适合处理TB级数据:
import dask.dataframe as dd # 读取目录下所有CSV文件(自动分块) ddf = dd.read_csv('data_directory/*.csv', index_col=0) # 按索引分组,保留每组b列最大的行 final_ddf = ddf.groupby(ddf.index).apply( lambda x: x[x['b'] == x['b'].max()], meta=ddf.dtypes ).reset_index(drop=True) # 计算并导出结果 final_df = final_ddf.compute()
关键优化技巧
- 数据类型压缩:处理前转换为更节省内存的类型,比如将
int64转为int32(数值范围允许的话),字符串列e转为category类型:df['a'] = df['a'].astype('int32') df['b'] = df['b'].astype('int32') df['e'] = df['e'].astype('category') - 避免不必要的中间变量:尽量减少链式操作产生的临时DataFrame,降低内存拷贝。
- 优先排序去重:排序后去重的性能远优于分组找最大值,尤其是超大规模数据集。
内容的提问来源于stack exchange,提问作者stackie
相关产品推荐
相关产品推荐

