首页 > 解决方案 > 加速熊猫块

问题描述

我可以使用一些帮助来加速这段代码。我假设 concat 操作是降低代码速度的原因,但我不确定。这一循环需要大约 20 倍的时间来执行我的函数中的其余代码。

df = pd.DataFrame()
for index, row in p_data_df.iterrows():
    test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
    if 'S' not in test_df.columns:
        test_df.insert(0, 'S', row.loc['S'])
        test_df.insert(1, 'C #', row.loc['C #'])
        test_df.insert(2, 'Num', row.loc['Num'])

    df = pd.concat([df, test_df], axis=0)

标签: pythonpandas

解决方案


pd.concat永远不要在 for 循环中调用。它导致二次复制:concat返回一个新的 DataFrame。必须为新的 DataFrame 分配空间,并且必须将旧 DataFrame 中的数据复制到新的 DataFrame 中。

因此,如果您的数据框有 N 行,您将需要 O (N^2) 个副本来完成循环。

使用字典列表或列表列表而不是数据框来累积结果,并在 for 循环之外使用结果列表创建数据框。这样你会节省大量的执行时间,pandas 不是为此做的。

你可以这样做:

list_res = []
for index, row in p_data_df.iterrows():
    test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
    if 'S' not in test_df.columns:
        test_df.insert(0, 'S', row.loc['S'])
        test_df.insert(1, 'C #', row.loc['C #'])
        test_df.insert(2, 'Num', row.loc['Num'])
    list_res.append(test_df)

df = pd.concat(list_res, axis=0)

更多加快代码速度的技巧

iterrows是迭代数据帧的最慢方法,因为必须将每一行转换为一个系列。如果您使用itertuples,则不会发生这种情况。您可以使用 itertuples,而无需过多更改代码,但会提高性能。

还有其他方法(矢量化、应用函数、Cython ......),它们需要对您的代码进行稍微更广泛的修改,但可以让您拥有更高效的代码。我留给你这个链接以获得更多信息。


推荐阅读