如何在 Pandas 中遍历 DataFrame 中的行

新手上路,请多包涵

我有一个熊猫数据框, df

    c1   c2
0  10  100
1  11  110
2  12  120

如何迭代此数据框的行?对于每一行,我希望能够通过列名访问其元素(单元格中的值)。例如:

 for row in df.rows:
   print(row['c1'], row['c2'])


我发现了一个 类似的问题,建议使用以下任何一种:

 for date, row in df.T.iteritems():

 for row in df.iterrows():

但我不明白 row 对象是什么以及如何使用它。

原文由 Roman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

DataFrame.iterrows 是一个产生索引和行(作为一个系列)的生成器:

 import pandas as pd

df = pd.DataFrame({'c1': [10, 11, 12], 'c2': [100, 110, 120]})
df = df.reset_index()  # make sure indexes pair with number of rows

for index, row in df.iterrows():
    print(row['c1'], row['c2'])

 10 100
11 110
12 120

原文由 waitingkuo 发布,翻译遵循 CC BY-SA 4.0 许可协议

如何遍历 Pandas DataFrame 中的行

答:不要* !

Pandas 中的迭代是一种反模式,只有在用尽所有其他选项时才应该这样做。您不应该在超过几千行的情况下使用名称中带有“ iter ”的任何函数,否则您将不得不习惯 大量 的等待。

你想打印一个 DataFrame 吗?使用 DataFrame.to_string()

你想计算一些东西吗?在这种情况下,按此顺序搜索方法(从 此处 修改的列表):

  1. 矢量化
  2. Cython 例程
  3. 列表理解(香草 for 循环)
  4. DataFrame.apply() : i) 可以在 Cython 中执行的归约,ii) Python 空间中的迭代
  5. DataFrame.itertuples()iteritems()
  6. DataFrame.iterrows()

iterrowsitertuples (都在这个问题的答案中获得很多选票)应该在非常罕见的情况下使用,例如为顺序处理生成行对象/名称元组,这确实是唯一的这些功能很有用。

诉诸权威

关于迭代 的文档页面 有一个巨大的红色警告框,上面写着:

遍历 pandas 对象通常很慢。在许多情况下,不需要手动遍历行 […]。

\* 它实际上比“不要”要复杂一点。 df.iterrows() 是这个问题的正确答案,但是“向量化你的操作”是更好的答案。我承认在某些情况下无法避免迭代(例如,某些操作的结果取决于为前一行计算的值)。但是,需要对库有一定的了解才能知道什么时候。如果您不确定是否需要迭代解决方案,您可能不需要。 PS:要了解更多关于我写这个答案的理由,请跳到最底部。


比循环更快: 矢量化Cython

pandas(通过 NumPy 或通过 Cythonized 函数)“矢量化”了大量基本操作和计算。这包括算术、比较、(大多数)归约、重塑(例如旋转)、连接和分组操作。查看有关 Essential Basic Functionality 的文档,找到适合您的问题的矢量化方法。

如果不存在,请随意使用自定义 Cython 扩展 编写您自己的。


下一个最好的事情: 列出理解*

如果 1) 没有可用的矢量化解决方案,2) 性能很重要,但还不够重要,无法解决代码的 cythonizing 问题,并且 3) 您正在尝试执行元素转换在你的代码上。有 大量证据 表明,对于许多常见的 Pandas 任务,列表推导式足够快(有时甚至更快)。

公式很简单,

 # Iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# Iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# Iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# Iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]

如果您可以将业务逻辑封装到一个函数中,则可以使用调用它的列表理解。您可以通过原始 Python 代码的简单性和速度来处理任意复杂的事情。

注意事项

列表理解假定您的数据易于使用——这意味着您的数据类型是一致的并且您没有 NaN,但这不能总是得到保证。

  1. 第一个更明显,但是在处理 NaN 时,如果存在内置的 pandas 方法(因为它们具有更好的极端情况处理逻辑),则更喜欢它们,或者确保您的业务逻辑包含适当的 NaN 处理逻辑。
  2. 在处理混合数据类型时,您应该迭代 zip(df['A'], df['B'], ...) 而不是 df[['A', 'B']].to_numpy() 因为后者隐式地将数据向上转换为最常见的类型。例如,如果 A 是数字而 B 是字符串, to_numpy() 会将整个数组转换为字符串,这可能不是您想要的。幸运的是 zip 将您的列连接在一起是最直接的解决方法。

*您的里程数可能会因上述 注意事项 部分中概述的原因而有所不同。


一个明显的例子

让我们通过添加两个 pandas 列的简单示例来演示差异 A + B 。这是一个可向量化的操作,因此很容易对比上面讨论的方法的性能。

对标代码,供大家参考。底部的行测量了一个用 numpandas 编写的函数,numpandas 是一种与 NumPy 大量混合以发挥最大性能的 Pandas 风格。除非您知道自己在做什么,否则应避免编写 numpandas 代码。尽可能坚持 API(即,更喜欢 vec 而不是 vec_numpy )。

然而,我应该提一下,它并不总是如此干脆。有时“什么是最佳操作方法”的答案是“这取决于您的数据”。我的建议是在选择一种方法之前先针对您的数据测试不同的方法。


我的个人意见*

对 iter 系列的各种替代方案进行的大多数分析都是通过性能的镜头进行的。然而,在大多数情况下,您通常会处理一个合理大小的数据集(不超过几千行或 10 万行),性能将仅次于解决方案的简单性/可读性。

在选择用于解决问题的方法时,这是我个人的偏好。

对于新手:

_矢量化_(如果可能) apply() ;列表理解; itertuples() / iteritems() ; iterrows() ; Cython

对于更有经验的人:

_矢量化_(如果可能) apply() ;列表理解;赛通; itertuples() / iteritems() ; iterrows()

对于任何可以向量化的问题,向量化都是最惯用的方法。始终寻求矢量化!如有疑问,请查阅文档,或在 Stack Overflow 上查找有关您的特定任务的现有问题。

我确实倾向于继续谈论 apply 在我的很多帖子中有多糟糕,但我承认对于初学者来说更容易理解它在做什么。此外,还有很多 apply 的用例已在 我的这篇文章中进行了 解释。

Cython 在列表中排名靠后,因为它需要更多的时间和精力才能正确完成。您通常永远不需要使用 pandas 编写需要这种性能水平的代码,即使是列表理解也无法满足。

*与任何个人意见一样,请带上大量盐!


进一步阅读

\* Pandas 字符串方法是“矢量化”的,因为它们在系列中指定但对每个元素进行操作。底层机制仍然是迭代的,因为字符串操作本质上很难向量化。


为什么我写这个答案

我从新用户那里注意到的一个常见趋势是提出“如何迭代我的 df 来执行 X?”形式的问题。显示在 for 循环中执行某些操作时调用 iterrows() 的代码。这就是为什么。没有被介绍过矢量化概念的图书馆新用户可能会将解决他们问题的代码设想为迭代他们的数据来做某事。不知道如何遍历 DataFrame,他们做的第一件事就是谷歌搜索并在这个问题上结束。然后他们看到接受的答案告诉他们如何去做,他们闭上眼睛并运行这段代码,而没有首先质疑迭代是否是正确的事情。

这个答案的目的是帮助新用户理解迭代不一定是所有问题的解决方案,可能存在更好、更快和更惯用的解决方案,值得花时间去探索它们。我并不是要开始一场迭代与矢量化的战争,但我希望新用户在使用这个库开发问题解决方案时得到通知。

原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题