如何在Pandas中对DataFrame中的行进行迭代?

python pandas rows dataframe


我有一个来自熊猫的 DataFrame

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

Output:

   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():

or

for row in df.iterrows():

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




Answer 1 waitingkuo


DataFrame.iterrows是产生索引和行的生成器

import pandas as pd
import numpy as np

df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])

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

Output: 
   10 100
   11 110
   12 120



Answer 2 cs95


如何在Pandas中对DataFrame中的行进行迭代?

答案:不要*

熊猫中的迭代是一种反模式,只有在用尽所有其他选项后才应执行此操作。您不应在名称中使用任何带有“ iter ”的函数超过数千行,否则您将不得不习惯很多等待。

您要打印一个DataFrame吗?使用 DataFrame.to_string()

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

  1. Vectorization
  2. Cython例程
  3. 列表推导(香草 for 循环)
  4. DataFrame.apply() :i)可以在cython中执行的约简操作,ii)在python空间中进行迭代
  5. DataFrame.itertuples() iteritems()
  6. DataFrame.iterrows()

iterrowsitertuples (在此问题的答案中都获得很多票)应该在非常罕见的情况下使用,例如生成行对象/命名元以进行顺序处理,这实际上是这些功能唯一有用的东西。

向当局提出上诉
迭代的文档页面上有一个巨大的红色警告框,其中指出:

迭代pandas对象一般都很慢。在许多情况下,不需要手动迭代记录[...]。

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


比循环快:矢量化Cython

熊猫(通过NumPy或通过Cythonized函数)对许多基本操作和计算进行了“向量化”。这包括算术,比较,(大多数)归约,整形(例如透视),联接和groupby操作。浏览有关基本基本功能的文档,以找到适合您问题的矢量化方法。

如果不存在,请使用自定义cython扩展名自行编写。


下一件事:列表理解

如果1)没有可用的向量化解决方案,2)性能很重要,但不够重要,不足以经历对代码进行cythonize的麻烦,并且3)您尝试执行元素转换,则列表理解应该是您的下一个调用端口在您的代码上。有大量证据表明,列表理解对于许多常见的熊猫任务足够快(甚至有时更快)。

这个公式很简单。

# 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
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

如果你能把你的业务逻辑封装成一个函数,你就可以用列表理解来调用它。你可以通过原始Python的简单和快速,让任意复杂的东西都能正常工作。


一个明显的例子

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

enter image description here

标杆代码,供大家参考。

然而,我应该提到的是,事情并不总是这么一刀切。有时,"什么是最好的操作方法 "的答案是 "这取决于你的数据"。我的建议是在确定一个方法之前,先对你的数据进行不同的测试。


延伸阅读

*熊猫字符串方法是“矢量化的”,因为它们在系列中已指定但可在每个元素上操作。底层机制仍然是迭代的,因为字符串操作本来就很难向量化。


我为什么要写这个答案

我从新用户那里注意到的一个普遍趋势是提出以下形式的问题:“如何在df上迭代以执行X?”。显示在for循环内执行某些操作时调用 iterrows() 的代码。这就是为什么。尚未引入向量化概念的图书馆新用户可能会想到通过迭代数据来执行某些操作来解决其问题的代码。不知道如何遍历DataFrame,他们要做的第一件事就是Google it并最终在这里出现这个问题。然后,他们看到被接受的答案告诉他们如何操作,然后他们闭上眼睛并运行此代码,而无需首先质疑迭代是否是正确的选择。

这个回答的目的是为了帮助新用户明白,迭代不一定能解决每个问题,可能存在更好的、更快的、更成语化的解决方案,值得投入时间去探索。我并不是想挑起一场迭代与向量化的战争,而是希望新用户在开发这个库的问题解决方案时,能够了解到这个库的问题。




Answer 3 viddik13


首先考虑是否真的需要遍历 DataFrame中的行。有关其他选择,请参见此答案

如果仍然需要遍历行,则可以使用以下方法。请注意一些其他 警告中未提及的重要警告

itertuples() 应该比 iterrows() 更快

但要注意的是,根据DOCs(Pandas 0.24.2目前)。

  • iterrows: dtype 可能不符合行与行

    因为iterrows为每一行返回一个Series,所以它不会在各行中保留 dtype(dtypes在DataFrame的各列之间都保留)。为了在遍历行时保留dtype,最好使用itertuples()返回值的namedtuple,通常比iterrows()快得多

  • 迭代行。不要修改行

    永远不应修改要迭代的内容。不能保证在所有情况下都能正常工作。根据数据类型,迭代器将返回副本而不是视图,并且对其进行写入将无效。

    使用DataFrame.apply()代替:

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

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

有关更多详细信息,请参见有关迭代的pandas文档




Answer 4 Wes McKinney


您应该使用 df.iterrows() 。尽管逐行迭代并不是特别有效,因为必须创建 Series 对象。




Answer 5 e9t


尽管 iterrows() 是一个不错的选择,但有时 itertuples() 可以更快:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop