Pandas groupby + 转换 6 亿条记录花费数小时

Pandas groupby + transform taking hours for 600 Million records

我的 DataFrame 3 个字段是帐户、月份和薪水。

account month              Salary
1       201501             10000
2       201506             20000
2       201506             20000
3       201508             30000
3       201508             30000
3       201506             10000
3       201506             10000
3       201506             10000
3       201506             10000

我正在对帐户和月份进行分组并计算组的薪水总和。然后删除重复项。

MyDataFrame['salary'] = MyDataFrame.groupby(['account'], ['month'])['salary'].transform(sum)
MyDataFrame = MyDataFrame.drop_duplicates()

预期输出如下:

account month              Salary
1       201501             10000
2       201506             40000
3       201508             60000
3       201506             40000

它适用于少数记录。我对 6 亿条记录进行了相同的 尝试,并且从 4-5 小时 开始一直在进行中。最初当我使用 pd.read_csv() 加载数据时,数据获得了 60 GB RAM,直到 1-2 小时 RAM 使用量在 90 到 120 GB 之间。 3 小时后进程占用了 236 GB RAM,它仍然是 运行。

如果有任何其他更快的替代方法可用于此,请提出建议。

编辑: 现在 15 分钟 在 df.groupby(['account', 'month'], sort=False)['Salary'].sum()

除非我误解了什么,否则您实际上是在做 aggregation - transform 用于当您需要原始帧形状中的数据时。这应该会更快一些,并且一步完成。

df.groupby(['account', 'month'])['Salary'].agg('sum')

只是为了跟进 chrisb 的回答和 Alexander 的评论,您确实会从 .sum().agg('sum') 方法中获得更多性能。这是三个的 Jupyter %%timeit 输出:

因此,chrisb 和 Alexander 提到的答案在您的非常小的示例数据集上大约快两倍。

此外,根据 Pandas API documentation,添加 kwarg sort=False 也有助于提高性能。因此,您的 groupby 应该类似于 df.groupby(['account', 'month'], sort=False)['Salary'].sum()。事实上,当我 运行 它时,它比上图中显示的运行速度快了大约 10%。

可能值得下载 Pandas 0.17.0 的开发版本。他们正在解锁控制多线程的 GIL。它将在 groupby 中本地实现,此博客 post 建议在组均值示例中将速度提高 3 倍。

http://continuum.io/blog/pandas-releasing-the-gil

http://pandas.pydata.org/