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

超大型DataFrame高效执行groupby与bfill的方法求助

问题描述

我有一个包含2768186062行的DataFrame,数据示例如下:

email                    email_created_date              country
a01423240@itesm.mx       2021-03-27 00:44:49+00:00          NaN
a01423240@itesm.mx       2022-01-14 16:27:18+00:00          IND
aalvarezleo@gmail.com    2021-05-14 13:24:15+00:00          NaN
aalvarezleo@gmail.com    2021-09-16 16:09:45+00:00          IND
acabazot@gmail.com       2021-03-27 00:38:37+00:00          NaN
acabazot@gmail.com       2022-01-14 12:25:28+00:00          IND
alt_wwe@hotmail.com      2022-09-22 22:08:50+00:00          NaN
alt_wwe@hotmail.com      2022-09-22 22:11:51+00:00          CA

需求:按email分组,对country列执行反向填充(bfill),预期输出如下:

email                    email_created_date              country
a01423240@itesm.mx       2021-03-27 00:44:49+00:00          IND
a01423240@itesm.mx       2022-01-14 16:27:18+00:00          IND
aalvarezleo@gmail.com    2021-05-14 13:24:15+00:00          IND
aalvarezleo@gmail.com    2021-09-16 16:09:45+00:00          IND
acabazot@gmail.com       2021-03-27 00:38:37+00:00          IND
acabazot@gmail.com       2022-01-14 12:25:28+00:00          IND
alt_wwe@hotmail.com      2022-09-22 22:08:50+00:00          CA
alt_wwe@hotmail.com      2022-09-22 22:11:51+00:00          CA

我用以下代码实现,但因数据量过大,执行时间已超1小时:

dt1[['country']]=(dt1
                  .sort_values(['email','email_created_date'])
                  .groupby(['email'], as_index=False)[['country']].fillna(method='bfill'))

需要更高效的实现方法,最大化处理效率。

高效解决方案

方法1:使用groupby.transform替代分组后fillna

groupby.transform直接对分组列应用bfill,避免额外的数据复制与索引操作,性能远优于原方法:

# 先确保数据按email和创建日期排序
dt1 = dt1.sort_values(['email', 'email_created_date'])
# 分组后用transform执行bfill
dt1['country'] = dt1.groupby('email')['country'].transform(lambda x: x.bfill())

方法2:利用email对应最终country值映射(针对你的数据特征)

从示例可见,每个email的最后一行country均为非空值,这种场景下可直接提取每组最终country值做映射填充,是效率最高的方案:

# 按email分组,提取每组最后一个非空的country值
email_country_map = dt1.sort_values(['email', 'email_created_date'])\
                       .groupby('email')['country'].last()
# 通过映射直接填充country列
dt1['country'] = dt1['email'].map(email_country_map)

该方法跳过逐行bfill操作,用字典映射完成填充,时间复杂度接近O(n),对超大规模数据的效率提升极为显著。

额外优化建议

  • 确保email列为字符串类型,避免分组时的类型转换开销
  • 若内存允许,将email列转为分类类型(dt1['email'] = dt1['email'].astype('category')),可大幅降低分组操作的内存占用与时间消耗
  • 使用pandas 2.0+版本时,启用pyarrow后端(设置pd.set_option('mode.copy_on_write', True)或使用pyarrow数据类型),可进一步提升大数据处理性能

内容的提问来源于stack exchange,提问作者nikki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:15:38