Pandas groupby:有效链接多个函数

Rom*_*rés 9 python performance pandas pandas-groupby

我需要对一个 DataFrame 进行分组,并在每个组上应用多个链式函数。

\n

我的问题与 pandas 基本相同- Groupby 两个函数cumsum然后应用于shift每个组。

\n

那里有关于如何获得正确结果的答案,但它们的性能似乎不太理想。因此,我的具体问题是:是否有比我下面描述的方法更有效的方法?

\n
\n

首先是一些大的测试数据:

\n
from string import ascii_lowercase\n\nimport numpy as np\nimport pandas as pd\n\n\nn = 100_000_000\nnp.random.seed(0)\ndf = pd.DataFrame(\n    {\n        "x": np.random.choice(np.array([*ascii_lowercase]), size=n),\n        "y": np.random.normal(size=n),\n    }\n)\n
Run Code Online (Sandbox Code Playgroud)\n

下面是各个功能的性能:

\n
%timeit df.groupby("x")["y"].cumsum()\n4.65 s \xc2\xb1 71 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n%timeit df.groupby("x")["y"].shift()\n5.29 s \xc2\xb1 54.1 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n

一个基本的解决方案是分组两次。这似乎不是最理想的,因为分组占总运行时间的很大一部分,并且应该只进行一次。

\n
%timeit df.groupby("x")["y"].cumsum().groupby(df["x"]).shift()\n10.1 s \xc2\xb1 63.5 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n

上述问题的公认答案建议使用apply自定义函数来避免此问题。然而由于某种原因,它的性能实际上比以前的解决方案差得多。

\n
def cumsum_shift(s):\n    return s.cumsum().shift()\n\n%timeit df.groupby("x")["y"].apply(cumsum_shift)\n27.8 s \xc2\xb1 858 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n
\n

您知道如何优化这段代码吗?特别是在我想要链接两个以上函数的情况下,性能提升可能会变得非常显着。

\n

Pra*_*ant 0

让我知道这是否有帮助,几周前我遇到了同样的问题。

\n

我只是通过拆分代码解决了这个问题。并创建一个单独的 groupby 对象,其中包含有关组的信息。

\n
# creating groupby object\ng = df.groupby('x')['y']\n\n%timeit g.cumsum()\n592 ms \xc2\xb1 8.67 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\n%timeit g.shift()\n1.7 s \xc2\xb1 8.68 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n