【发布时间】:2020-12-26 08:59:39
【问题描述】:
我正在尝试使用正在创建的列的移位值创建一个新的 Pandas DataFrame 列。
我能够做到这一点的唯一方法是遍历太慢并导致我的代码出现瓶颈的数据。
import pandas as pd
df = pd.DataFrame([1,6,2,8], columns=['a'])
df.at[0, 'b'] = 5
for i in range(1, len(df)):
df.loc[i, ('b')] = (df.a[i-1] + df.b[i-1]) /2
我尝试使用 shift 但它不起作用。它填充第 1 行的值,其余部分填充 NaN。我假设此方法无法即时读取新创建的值。
df.loc[1:, ('b')] = (df.a.shift() + df.b.shift()) /2
更新
通过在迭代中使用df.at 而不是df.loc,我能够显着减少时间
def with_df_loc(df):
for i in range(1, len(df)):
df.loc[i, ('b')] = (df.a[i-1] + df.b[i-1]) /2
return df
def with_df_at(df):
for i in range(1, len(df)):
df.at[i, 'b'] = (df.a[i-1] + df.b[i-1]) /2
return df
%timeit with_df_loc(df)
183 ms ± 75.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit with_df_at(df)
19.4 ms ± 2.74 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
此时间基于 150 行的较大数据集。考虑到df.rolling(20).mean() 大约需要 3 毫秒,我认为这可能是我能做的最好的了。
感谢大家的回答,如果需要进一步优化我会考虑Asish M对numba的建议。
【问题讨论】:
-
pandas 确实没有简单的方法来处理递归的东西 - 查看
numba以加快 for 循环。 -
作为替代方案 - scipy.signal.filter 在这里似乎很有用 - 请参阅 stackoverflow.com/questions/26267809/…
-
您还在为上述循环寻找更高效的解决方案吗?我有点困惑,因为问题和答案不匹配。
-
@cs95 我对问题进行了一些编辑,因为其中一个答案有效,但这只是因为 df['a'] 列值按数字顺序排列,如果该列包含随机值,它应该可以工作。我可以通过在迭代中使用
df.at而不是df.loc来加快速度,但是如果您知道另一种方式,我很想听听。一直在寻找改进代码的方法。
标签: python pandas dataframe numba