You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效在Pandas中按指定列分组并保留size_col最大值对应的行(处理500万行数据集)

如何高效处理百万级DataFrame:按分组保留最大值行?

问题场景

我手头有个500万行、7列的大型DataFrame df1:

>>> df1
col_1 col_2 size_col other_col
0    aaa    abc        4       zxc
1    aaa    abc        3       xcv
2    aaa    abc        1       cvb
3    bbb    bbc        7       vbn
4    bbb    bbc        3       bnm
5    ccc    cbc        1       asd
6    ddd    dbc        9       sdf
7    ccc    cbc        3       dfg
8    ccc    cbc        1       fgh

需求很明确:按col_1和col_2分组,每组只保留size_col值最大的那一行,最终得到df2:

>>> df2
col_1 col_2 size_col other_col
0    aaa    abc        4       zxc
3    bbb    bbc        7       vbn
6    ddd    dbc        9       sdf
7    ccc    cbc        3       dfg

想请教下,针对这种大数据量的场景,怎么处理最高效?


高效解决方案

对于500万行这种量级的数据,咱们得优先选性能好、内存占用可控的方法,下面两种都是经过实践验证的靠谱方案:

方法1:排序后去重(首推,性能最优)

思路是先把数据按分组列排序,再按size_col降序排列,这样每组里最大值的行就排在最前面,然后用drop_duplicates保留每组的第一行就行:

# 先按分组列升序排,再按size_col降序排,确保每组最大值行在最前面
df_sorted = df1.sort_values(by=['col_1', 'col_2', 'size_col'], ascending=[True, True, False])
# 按col_1和col_2去重,只保留每组第一行(也就是size_col最大的行)
df2 = df_sorted.drop_duplicates(subset=['col_1', 'col_2'], keep='first')
# 要是需要恢复原数据的索引顺序,加这一行就行(可选)
# df2 = df2.sort_index()

这个方法的优势在于:排序和去重都是pandas底层优化的矢量化操作,处理百万级数据时速度比groupby方法更快,内存压力也更小。

方法2:GroupBy + idxmax(逻辑更直观)

如果觉得排序的思路绕,也可以用分组找最大值索引的方法,逻辑更直接:

# 按col_1和col_2分组,找出每组size_col最大的行的索引
max_row_indices = df1.groupby(['col_1', 'col_2'])['size_col'].idxmax()
# 根据索引提取对应的行
df2 = df1.loc[max_row_indices]

这个方法容易理解,但在处理超大数据量时,groupby的内存开销会比方法1略高一点,不过对于500万行的场景,完全能hold住。


额外提醒

  • 如果同一组里有多个行的size_col都是最大值,上面两种方法都会保留第一个出现的那一行。要是想保留所有最大值行,可以把drop_duplicates里的keep='first'改成keep='all',或者用transform配合布尔索引实现。
  • 建议用pandas 1.3以上的版本,新版本对大数据量的处理性能有不少优化。
  • 要是内存实在紧张,可以考虑分块处理,但500万行7列的数据,只要你内存有16G以上,用上面的方法就能快速跑完。

内容的提问来源于stack exchange,提问作者Naveen Reddy Marthala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:12:28