如何加快熊猫数据框迭代

Posted

技术标签:

【中文标题】如何加快熊猫数据框迭代【英文标题】:How to speed up pandas dataframe iteration 【发布时间】:2021-09-17 14:51:01 【问题描述】:

我们在项目中使用了 pandas 数据框,我们意识到由于 pandas 数据框的计算速度很慢,我们的程序非常慢。我与你分享了我们的代码。

   df_item_in_desc = pd.DataFrame(columns = df.columns) # to hold all satisfied results
    
    for index in df.shape[0]:
        s1 = set(df.iloc[index]['desc_words_short'])
    
        if item_number in s1:   
            df_item_in_desc = df_item_in_desc.append(df.iloc[index])

我们检查项目名称是否在另一列 desc_words_short 中,然后我们将该行附加到另一个数据框 (df_item_in_desc)。这是一个简单的逻辑,但要获得这样的行,我们应该遍历所有数据帧并检查该条件。我们的数据框有点大,运行此代码需要更多时间。我们怎样才能加快这个过程,我们可以在这个任务中使用Cpu parallelization,还是别的什么?

注意:我们实际上尝试过 Cpu 并行化,但不会成功。

【问题讨论】:

你运行它的机器的内存是多少,你最大的数据集的大小是多少? Ram 为 8 GB,我们的数据集中有大约 100000 个样本。实际上我们的数据集的大小不到 100 MB,并没有那么大。 你能举一个你的数据的例子吗?项目有多多样化?您可以尝试首先为每列构建一组项目,以避免在每次迭代时必须遍历所有行。但请注意,实现目标的各种策略的效率会因数据的性质而有很大差异。 @mozway 感谢您的回复。实际上变量 item_number 保存项目的名称,列 desc_words_short 保存字符串列表,我们想检查项目名称是否在列 desc_words_short 中。 好的,但这并没有解决关于数据类型的问题。根据您是否有很多不同的项目、许多相似的项目、重复项目等,将改变尝试解决问题的方式。由于您的目标是优化速度,我认为如果不提供数据集,您将无法获得体面的响应。 【参考方案1】:

所以看起来您正在遍历每一行并查看desc_words_short 列的值。对于每个值,如果该值(可能是一个列表)包含item_number,那么您希望将该行添加到df_item_in_desc

如果这是目标,您可以像这样加快速度:

import pandas as pd

item_number = 'a'
df = pd.DataFrame('desc_words_short':[['a','a','b'],['b','d'],['c','c']])

print(df)

  desc_words_short
0        [a, a, b]
1           [b, d]
2           [c, c]

mask = df['desc_words_short'].apply(lambda x: item_number in x)
df_item_in_desc = df.loc[mask]

print(df_item_in_desc)

  desc_words_short
0        [a, a, b]

我不确定set 的意义是什么,因为item_number 会在完整列表或集合中,所以这是一个毫无意义的额外计算

【讨论】:

不用担心.. 很想知道实施后的速度 实际上花了几秒钟,但现在需要 0.08 s【参考方案2】:

您也可以使用列表推导。我们应该避免使用df.apply,并将其作为最后的手段。

在较大的数据集上,列表理解会更快。此处回答的基准:link。答案本身就是智慧的结晶。

引用基准:

%timeit df[df.apply(lambda x: x['Name'].lower() in x['Title'].lower(), axis=1)]
%timeit df[[y.lower() in x.lower() for x, y in zip(df['Title'], df['Name'])]]

2.85 ms ± 38.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
788 µs ± 16.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
import pandas as pd
item_number = 'a'
df = pd.DataFrame('desc_words_short':[['a','a','b'],['b','d'],['c','c']])
df[[ item_number in x for x in df['desc_words_short']]]

数据框:

  desc_words_short
0        [a, a, b]
1           [b, d]
2           [c, c]

输出:

  desc_words_short
0        [a, a, b]

参考: https://***.com/a/54432584/6741053

【讨论】:

我认为这确实是您触摸的好点。我也会用这种方式检查。非常感谢@รยקคгรђשค的回答 @Ali 乐于助人。如果您可以比较这两种方法并在单独的答案中提供基准,那就太好了,这将对未来的访问者有所帮助。

以上是关于如何加快熊猫数据框迭代的主要内容,如果未能解决你的问题,请参考以下文章

如何在熊猫中迭代数据框时保留数据类型?

如何迭代熊猫数据框的列以运行回归

如何迭代熊猫数据框并创建新列

如何按天拆分熊猫数据框或系列(可能使用迭代器)

涉及即时数据框对象的嵌套熊猫迭代

可从熊猫数据框迭代