优化pandas中运行时的过滤功能

kos*_*tas 5 python filter pandas

def filter_data(df, raw_col,threshold,filt_col):
    df['pct'] = None
    df[filt_col] = None
    df[filt_col][0] = df[raw_col][0]
    max_val = df[raw_col][0]
    for i in range(1,len(df)):
        df['pct'][i] = (df[raw_col][i] - max_val)*1.0 / max_val
        if abs(df['pct'][i]) < threshold:
            df[filt_col][i] = None
        else:
            df[filt_col][i] = df[raw_col][i]
            max_val = df[raw_col][i]
    df = df.dropna(axis=0, how='any').reset_index()
    return df


from random import randint
some_lst = [randint(50, 100) for i in range(0,50)]
some_df = pd.DataFrame({'raw_col':some_lst})
some_df_filt = filter_data(some_df,'raw_col',0.01,'raw_col_filt')
Run Code Online (Sandbox Code Playgroud)

创建新列(filt_col)的目标是使用以下逻辑删除数字列(raw_col)中的记录; 如果两个相邻行之间的变化率小于阈值,则移除后者.它有效,但在运行时间方面效率很低.有关如何优化它的任何提示?

raf*_*elc 4

IIUC,您可以非常简单地使用.pct_change()loc

第一的

df['pctn'] = df.raw_col.pct_change()
Run Code Online (Sandbox Code Playgroud)

然后

threshold  = 0.01
df.loc[df.pctn.abs() >= threshold]
Run Code Online (Sandbox Code Playgroud)

您可以检查该解决方案是否产生与您的结果相同的结果,您说它有效,但速度很慢

df.loc[df.pctn.abs() >= 0.01].raw_col.tolist() == some_df_filt.raw_col.tolist()
True
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。测试时,加速比是几个数量级。问题中的算法使用 pandas/numpy api 之外的大量代码在数据帧上运行(从效率的角度来看,有效地渲染 pandas/numpy 无用),这个答案有效地使用了 api,将事情排除在 python 领域之外。从实际角度来看,您不需要比这更好的东西了。我蹩脚的桌面使用原始算法需要几分钟才能完成 1000 个数字,而现在我可以在 1.1 秒内完成 10,000,000 个数字。 (2认同)