当前位置: 首页 > 知识库问答 >
问题:

如何在Pandas中迭代数据帧中的行

曹理
2023-03-14

我有一个来自熊猫的数据帧:

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print 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对象是什么,以及如何使用它。

共有2个答案

东郭阳德
2023-03-14

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

是否打印数据帧?使用dataframe.to_string()

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

  1. 矢量化
  2. Cython例程
  3. 列表理解(用于循环的vanilla)
  4. dataframe.apply():i)可以在Cython中执行的 约简,ii)在Python空间中的迭代
  5. DataFrame.iterTuples()iterItems()
  6. dataframe.iterrows()

iterrowsitertuples(在回答这个问题时都得到了很多投票)应该在非常罕见的情况下使用,例如生成用于顺序处理的行对象/nameTuple,这实际上是这些函数唯一有用的东西。

向主管当局上诉

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

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

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

大量的基本操作和计算都被pandas“矢量化”(通过NumPy或Cythonized函数)。这包括算术、比较、(最大)约简、整形(如枢转)、联接和groupby操作。查看有关基本功能的文档,为您的问题找到合适的矢量化方法。

如果不存在,请使用自定义的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. 在处理混合数据类型时,应迭代zip(df['a'],df['b'],...)而不是df[['a','b']].to_numpy(),因为后者将数据隐式上传到最常见的类型。例如,如果A是数值,B是字符串,to_numpy()将把整个数组转换为字符串,这可能不是您想要的。幸运的是,zip将列ping在一起是最简单的解决方法。

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

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

标杆代码,供大家参考。底部的行测量了一个用numpandas编写的函数,这是一种Pandas样式,它与NumPy大量混合,以挤出最大的性能。除非您知道自己在做什么,否则应该避免编写numpandas代码。坚持尽可能使用API(例如,首选vec而不是vec_numpy)。

不过,我要提到的是,事情并不总是这样一劳永逸。有时候“什么是一个操作最好的方法”的答案是“这取决于你的数据”。我的建议是,在确定一种方法之前,先对你的数据测试不同的方法。

>

  • 10分钟的pandas和基本功能-有用的链接,向您介绍pandas及其矢量化*/Cythonized函数库。

    提高性能--关于提高Pandas标准操作的文件入门

    熊猫的for-loop真的不好吗?我什么时候该关心?-我对列表的理解及其对各种操作(主要是涉及非数字数据的操作)的适用性进行了详细的记录

    什么时候我应该(不)希望在代码中使用pandas apply()?-apply慢(但不如iter*系列慢。但是,在某些情况下,可以(或应该)将apply作为一种重要的替代方法,特别是在某些groupby操作中)。

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

    我从新用户那里注意到的一个常见趋势是问“我如何迭代我的df来做X?”这一形式的问题。显示在for循环内执行某些操作时调用iterrows()的代码。原因就在这里。库的一个新用户,如果还没有被介绍到矢量化的概念,可能会把解决他们问题的代码想象成通过迭代他们的数据来做一些事情。不知道如何迭代一个数据帧,他们做的第一件事是谷歌它,并结束在这里,在这个问题。然后他们看到被接受的答案告诉他们如何去做,然后他们闭上眼睛运行这段代码,而从来没有首先问过迭代是否不是正确的事情。

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

  • 燕烨
    2023-03-14

    dataframe.iterrows是生成器,它生成索引和行(作为一个系列):

    import pandas as pd
    
    df = pd.DataFrame({'c1': [10, 11, 12], 'c2': [100, 110, 120]})
    
    for index, row in df.iterrows():
        print(row['c1'], row['c2'])
    
    10 100
    11 110
    12 120
    
     类似资料:
    • 数据帧: 我有一段代码逐列遍历数据帧: 我需要删除它是NaN的行。我该怎么做?我已经尝试了. isnull()和. Notnull(),但它们返回错误

    • 在编程方面,我是一个新手,特别是熊猫。我也很抱歉,我问了一个已经在SF上提到的问题:我并不真正理解这个问题的现有答案。可能重复,但这个答案对新手来说很容易理解,如果不太全面的话。

    • 我有一个熊猫数据框,看起来像这样(它是一个相当大的) 现在我想逐行迭代,当我遍历每一行时,每一行中的的值可能会根据某些条件而改变,我需要查找另一个数据帧。 现在,我如何在迭代时更新它。尝试了一些没用的东西。 这些方法似乎都不管用。我看不到数据框中更新的值。

    • 我有这样的数据: 我想创建一个新的列,将成本转换为美元。只是提一下,有12种货币。 这是我所写的: 使用这段代码,我得到了一个错误。

    • 问题内容: 我有一个DataFrame来自pandas的: 输出: 现在,我要遍历该框架的行。对于每一行,我希望能够通过列名访问其元素(单元格中的值)。例如: pandas有可能这样做吗? 我发现了类似的问题。但这并不能给我我所需的答案。例如,建议在那里使用: 要么 但是我不了解row对象是什么以及如何使用它。 问题答案: 是一个生成器,它同时生成索引和行(作为系列):

    • 我需要对pandas数据帧进行迭代,以便将每一行作为带有的函数(实际上是类构造函数)的参数传递。这意味着每一行都应该像字典一样,具有键、列名和值(每行对应的值)。