我需要对一个DataFrame进行分组,并在每个分组上应用几个链接函数。
我的问题与pandas - Groupby two functions中的基本相同:在每组上依次应用cumsum
和shift
。
关于如何获得正确的结果,有一些答案,但它们似乎有次优的性能。我的具体问题是:是否有比我下面描述的方法更有效的方法?
首先是一些大型测试数据:
from string import ascii_lowercase
import numpy as np
import pandas as pd
n = 100_000_000
np.random.seed(0)
df = pd.DataFrame(
{
"x": np.random.choice(np.array([*ascii_lowercase]), size=n),
"y": np.random.normal(size=n),
}
)
以下是每个功能的性能:
%timeit df.groupby("x")["y"].cumsum()
4.65 s ± 71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit df.groupby("x")["y"].shift()
5.29 s ± 54.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
一个基本的解决方案是分组两次,这似乎不是最佳的,因为分组是整个运行时的一大部分,应该只进行一次。
%timeit df.groupby("x")["y"].cumsum().groupby(df["x"]).shift()
10.1 s ± 63.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
上述问题的公认答案建议使用带有自定义函数的apply
来避免这个问题,但由于某些原因,它实际上比以前的解决方案性能差得多。
def cumsum_shift(s):
return s.cumsum().shift()
%timeit df.groupby("x")["y"].apply(cumsum_shift)
27.8 s ± 858 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
你知道如何优化这段代码吗?特别是在我想链接两个以上函数的情况下,性能的提高会变得非常显著。
2条答案
按热度按时间rkue9o1l1#
如果有帮助,请告诉我,几周前我也有同样的问题。
我通过拆分代码并创建一个包含组信息的单独groupby对象来解决这个问题。
e0bqpujr2#
我建议尝试一下
transform
而不是apply
试试这个:
或者,也可以尝试使用
我非常肯定
pipe
比apply或transform更高效。请告诉我们它是否工作正常