从数据帧的每一行中提取信息而无需循环

Posted

技术标签:

【中文标题】从数据帧的每一行中提取信息而无需循环【英文标题】:Extract info from each row of a dataframe without a loop 【发布时间】:2021-07-24 16:49:29 【问题描述】:

我有一个大数据框(约 500,000 行)。处理每一行都会给我一个 Counter 对象(一个包含对象计数的字典)。我想要的输出是一个新的数据框,其中列标题是正在计算的对象(字典中的键)。我正在遍历行,但是它需要很长时间。我知道在 Pandas 中应该避免循环,有什么建议吗?

out_df = pd.DataFrame()
for row in input_df['text']:
    tokens = nltk.word_tokenize(row)
    pos = nltk.pos_tag(tokens)
    count = Counter(elem[1] for elem in pos)
    out_df = out_df.append(count, ignore_index=True)

作为指示,Counter(elem[1] for elem in pos) 看起来像 Counter('NN':8, 'VBZ': 2, 'DT':3, 'IN': 4)

【问题讨论】:

【参考方案1】:

我认为可能必须使用矢量化解决方案:“遍历 pandas 对象通常很慢。在许多情况下,不需要手动迭代行并且可以避免(使用)矢量化解决方案:许多操作可以使用内置方法或 NumPy 函数执行(布尔)索引。" 来自https://towardsdatascience.com/you-dont-always-have-to-loop-through-rows-in-pandas-22a970b347ac

【讨论】:

我找不到向量化处理每一行的函数的方法——这可能是最有效的方法。【参考方案2】:

我认为在数据帧上使用附加功能非常低效(每次都必须为整个数据帧重新分配内存)。

DataFrames 用于分析数据和轻松添加列,而不是行。

所以我认为更好的方法是首先创建列表(列表为mutable),然后将其转换为数据框。

我对 nltk 不熟悉,所以我无法实际测试它,但以下几行应该可以工作:

out_data = []
for row in input_df['text']:
    tokens = nltk.word_tokenize(row)
    pos = nltk.pos_tag(tokens)
    count = Counter(elem[1] for elem in pos)
    out_data.append(count)
out_df = pd.DataFrame(out_data)

您可能需要添加以下内容以删除任何 NaN 并将最终计数转换为整数:

out_df = out_df.fillna(0).astype(int)

然后删除列表以释放内存:

del out_data

【讨论】:

谢谢。它在大约 15 分钟内完成了这项工作 优秀。如果您需要更快地完成它,那么下一步可能是并行处理解决方案。我认为使用Dask 很容易做到这一点。见this answer我写的一个文件处理问题。

以上是关于从数据帧的每一行中提取信息而无需循环的主要内容,如果未能解决你的问题,请参考以下文章

芹菜任务设置与视频帧的内存缓存作为python中的循环缓冲区策略

我们可以在数据帧的每一行上使用 spark sql 函数吗?

如何将每一行熊猫数据帧附加到另一个数据帧的每一行

如何在巨大数据帧的每一行中查找前 n 个值的列索引

R:从一个数据帧中提取行,基于列名匹配来自另一个数据帧的值

将数据帧返回函数应用于基础数据帧的每一行