我可以将 `eval` 与 `rolling()` 结合使用吗?

Can I use `eval` with `rolling()`?

假设我有一个 pandas 数据框,我想创建一个使用滚动 window 的新列,例如:

test = pd.DataFrame({'x': range(0,100)})
test['rol'] =  test.rolling(20,center=False).sum()

有没有办法使用 eval 函数来做到这一点 inplace?


奖金:我想了解 evalassigndf['some_column_name'] = ...

之间可能存在的性能问题(内存和速度)

使用assign制作你的烟斗:

test = (pd.DataFrame({'x': range(0,100)})
          .assign(rol= lambda s: s.rolling(20,center=False).sum())
       )

输出:

     x     rol
0    0     NaN
1    1     NaN
2    2     NaN
...
97  97  1750.0
98  98  1770.0
99  99  1790.0

注意。大多数操作都是 NOT 在 pandas 中完成的(从某种意义上说,不涉及复制),即使操作具有 inplace 关键字。该操作通常在副本上完成并替换原件。围绕这个参数的混淆是为什么 inplace 可能在未来的 pandas 版本中被弃用

您可以使用 assign 但这会创建您的数据框的副本:

df = df.assign(rol=df['x'].rolling(20).sum())

或者像你一样使用直接赋值:

df['rol'] = df['x'].rolling(20,center=False).sum())

但是 eval 不可能与 rolling window

您的示例的性能:

%timeit df.assign(rol=df['x'].rolling(20,center=False).sum())
845 µs ± 67.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df['rol'] =  df['x'].rolling(20).sum()
699 µs ± 39.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

对于 1,000,000 条记录:

%timeit df.assign(rol=df['x'].rolling(20,center=False).sum())
28.5 ms ± 1.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit df['rol'] =  df['x'].rolling(20).sum()
36.4 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

对于大型数据集pd.assign变得比直接赋值更好(我不知道为什么...)