【问题标题】:Can I use `eval` with `rolling()`?我可以在 `rolling()` 中使用 `eval` 吗?
【发布时间】:2021-10-20 04:51:57
【问题描述】:

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

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

有没有办法使用eval 函数来做到这一点就地


奖励:我想了解evalassigndf['some_column_name'] = ... 之间可能存在的性能问题(内存和速度)

【问题讨论】:

  • eval 是什么意思?滚动不支持'eval'。
  • 我想你可能已经回复了。例如,如果我想添加另一个名为“add2”的列,我可以在上面的示例中使用test.eval('add2 = x+2')。我想知道是否有办法将evalrolling 结合起来,但从你所说的来看,它不受支持。
  • 我想你的意思是assign,而不是eval

标签: python pandas dataframe rolling-computation


【解决方案1】:

您可以使用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 变得比直接赋值更好(我不知道为什么......)

【讨论】:

  • 对于大型数据集,就内存和/或计算速度而言,后者(直接分配)是否更可取?
  • 但这不是一个管道,并且已经是 OP 一开始所做的,不是吗?
  • @NMech。我不知道我的基准测试是否不好,但对于大型数据集,pd.assign 比直接分配更好。
【解决方案2】:

使用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 版本中可能会被弃用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    相关资源
    最近更新 更多