首页 > Python > 如何在 Pandas 中循环访问数据帧中的行

如何在 Pandas 中循环访问数据帧中的行

上一篇 下一篇

网友问题:
我有一个熊猫数据帧,:
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

网友回答:
1、

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

2、
如何在 Pandas 中循环访问数据帧中的行
答:不要*

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

是否要打印数据帧?使用 DataFrame.to_string()。

你想计算什么吗?在这种情况下,请按以下顺序搜索方法(从此处修改的列表):

  1. 矢 量化
  2. 赛通套路
  3. 列表推导(香草循环)for
  4. DataFrame.apply(): i) 可以在 Cython 中执行的归约,ii) Python 空间中的迭代
  5. DataFrame.itertuples() 和 iteritems()
  6. DataFrame.iterrows()

iterrows并且(两者都在回答这个问题时获得许多投票)应该在非常罕见的情况下使用,例如生成行对象/名称元组以进行顺序处理,这实际上是这些函数唯一有用的东西。itertuples

向当局上诉

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

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

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


比循环更快:矢量化,Cython

大量的基本操作和计算被熊猫“矢量化”(通过NumPy,或通过Cythonized函数)。这包括算术、比较、(大多数)约简、重塑(如透视)、联接和分组依据运算。浏览有关基本基本功能的文档,找到适合您问题的矢量化方法。

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


下一个最好的事情:列表推导*

如果 1) 没有可用的矢量化解决方案,2) 性能很重要,但还不够重要,无法经历代码的麻烦,以及 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. 处理混合数据类型时,应进行迭代,而不是因为后者会隐式将数据向上转换为最常见的类型。例如,如果 A 是数字,B 是字符串,则将整个数组转换为字符串,这可能不是您想要的。幸运的是,将您的列 ping 在一起是最直接的解决方法。zip(df['A'], df['B'], ...)df[['A', 'B']].to_numpy()to_numpy()zip

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


我的个人意见*

对iter家族的各种替代品进行的大多数分析都是通过性能的视角进行的。但是,在大多数情况下,您通常会处理大小合理的数据集(不超过几千或 100K 行),性能将次于解决方案的简单性/可读性。

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

对于新手:

矢量化(如果可能);应用();列出理解;itertuples()/iteritems();迭代();赛通

对于更有经验的人:

矢量化(如果可能);应用();列出理解;赛通;itertuples()/iteritems();迭代行()

矢量化是任何可以矢量化问题的最惯用方法。始终寻求矢量化!如有疑问,请查阅文档,或在 堆栈溢出 查找有关您的特定任务的现有问题。

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

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

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


延伸阅读

  • 10 分钟致 pandas 和基本基本功能 – 有用的链接,向您介绍 Pandas 及其矢量化*/cythonized 函数库。
  • 增强性能 – 来自增强标准 Pandas 操作的文档入门
  • 熊猫的for循环真的很糟糕吗?我什么时候应该关心?– 我详细撰写了关于列表推导及其对各种操作(主要是涉及非数字数据的操作)的适用性的文章
  • 我什么时候应该(不)在我的代码中使用 pandas apply()?– 很慢(但不像家庭那么慢。但是,在某些情况下,可以(或应该)考虑将其视为一种严肃的替代方案,尤其是在某些操作中)。applyiter*applyGroupBy

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


我为什么写这个答案

我从新用户那里注意到的一个常见趋势是提出“我如何迭代我的 df 来做 X?”形式的问题。显示在循环内执行某些操作时调用的代码。原因如下。尚未了解矢量化概念的库新用户可能会将解决问题的代码设想为迭代其数据以执行某些操作。不知道如何迭代数据帧,他们做的第一件事就是谷歌它并结束在这里,在这个问题上。然后,他们看到接受的答案告诉他们如何操作,然后他们闭上眼睛运行此代码,而无需首先质疑迭代是否正确。iterrows()for

这个答案的目的是帮助新用户理解迭代不一定是每个问题的解决方案,并且可能存在更好,更快和更惯用的解决方案,并且值得花时间探索它们。我并不是要发起一场迭代与矢量化的战争,但我希望新用户在开发有关此库问题的解决方案时了解情况。

3、

首先考虑是否确实需要循环访问数据帧中的行。有关替代方案,请参阅此答案。

如果仍需要迭代行,可以使用以下方法。请注意一些重要的警告,这些警告在任何其他答案中都没有提到。

  • DataFrame.iterrows()
      for index, row in df.iterrows():
          print(row["c1"], row["c2"])
    
  • DataFrame.itertuples()
      for row in df.itertuples(index=True, name='Pandas'):
          print(row.c1, row.c2)
    

itertuples()应该比iterrows()

但请注意,根据文档(目前 pandas 0.24.2):

  • 迭代行:可能与行不匹配dtype

由于迭代行为每一行返回一个序列,因此它不会跨行保留 dtype(dtype 在数据帧的列中保留)。为了在迭代行时保留 dtype,最好使用 itertuples(),它返回值的命名元组,并且通常比 iterrows() 快得多。

  • 迭代行:不修改行

永远不应该修改你正在迭代的东西。这并不能保证在所有情况下都有效。根据数据类型,迭代器返回副本而不是视图,写入该副本将不起作用。

请改用 DataFrame.apply():

    new_df = df.apply(lambda x: x * 2, axis = 1)
  • itertuples:

如果列名称是无效的 Python 标识符、重复或以下划线开头,则列名称将重命名为位置名称。对于大量列 (>255),将返回常规元组。

有关更多详细信息,请参阅有关迭代的熊猫文档。

模板简介:该模板名称为【如何在 Pandas 中循环访问数据帧中的行】,大小是暂无信息,文档格式为.html,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 217次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 html
  • 文件大小 暂无信息
  • 上传时间 02-07
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
企业网站 微信公众平台 响应式 自适应 微信图片 微信模板 微信文章 单页式简历模板 微信素材 html5
您可能会喜欢的其他模板