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


1943

我有一个DataFrame熊猫来的:

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对象是什么以及如何使用它。


11
df.iteritems()遍历列而不是行。因此,要使其遍历行,必须进行转置(“ T”),这意味着您将行和列彼此更改(在对角线上反射)。结果,当您使用df.T.iteritems()
Stefan Gruenwald

11
如果您是该线程的新手并且是熊猫的初学者,请不要迭代!在数据帧上进行迭代是一种反模式,除非您希望习惯大量等待,否则不应该执行此操作。根据您要尝试执行的操作,可能会有更好的选择iter*函数应在极少数情况下使用。也有关
cs95

18
与cs95所说的相反,有充分的理由要在数据帧上进行迭代,因此,新用户不应感到灰心。一个示例是如果您要使用每一行的值作为输入来执行一些代码。同样,如果您的数据框很小(例如少于1000个项目),则性能并不是真正的问题。
oulenz

1
@oulenz:如果出于某种奇怪的原因,您想面对使用API​​的目的(高性能数据转换),那么请来我这里。但是至少,不要使用iterrows,有更好的方法遍历DataFrame,此时最好也遍历列表列表。如果您除了在DataFrames上进行迭代之外什么都不做,那么使用DataFrame根本没有任何好处(假定对其进行迭代是您唯一要做的事情)。只是我的2c。
cs95

7
我第二@oulenz。据我所知pandas,即使数据集很小,读取csv文件的首选方法。它只是更容易编程使用API操纵数据
克里斯-

Answers:


2627

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

206
注意:“因为iterrows为每一行返回一个Series,所以它不会在各行之间保留dtype。” 另外,“您永远不要修改要迭代的内容。” 根据熊猫0.19.1文档
viddik13'2013/

3
@ viddik13非常感谢。因此,我遇到了一个数字值,例如431341610650where读为的情况4.31E+11。是否有保留dtypes的方法?
阿齐兹·阿尔托

26
@AzizAlto使用itertuples,如下所述。另请参阅pandas.pydata.org/pandas-docs/stable/generation/…–
Axel

100
不要使用它。Itertuples更快,并且保留数据类型。更多信息
James L.

11
文件:“通过迭代大熊猫对象通常是缓慢的。在许多情况下,手动遍历行不需要[...]。” 您的答案是正确的(在问题的上下文中),但是在任何地方都没有提及,因此它不是一个很好的答案。
95

450

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

答案:不要*

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

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

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

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

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

呼吁授权迭代中
的docs页面上有一个巨大的红色警告框,指出:

遍历熊猫对象通常很慢。在许多情况下,不需要手动在行上进行迭代。

*实际上比“不要”复杂一些。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 - 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时,如果存在内置熊猫方法,则更喜欢它们(因为它们具有更好的极端情况处理逻辑),或者确保您的业务逻辑包括适当的NaN处理逻辑。
  2. 在处理混合数据类型时,您应该进行迭代,zip(df['A'], df['B'], ...)而不是df[['A', 'B']].to_numpy()因为后者隐式地将数据转换为最常见的类型。例如,如果A为数字而B为字符串,to_numpy()则将整个数组转换为字符串,这可能不是您想要的。幸运的是,zip将所有列一起ping是最简单的解决方法。

* YMMV出于上面“ 注意事项”部分概述的原因。


一个明显的例子

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

在此处输入图片说明

基准测试代码,供您参考。

但是,我应该指出的是,并非总是如此。有时,“什么是最佳操作方法”的答案是“取决于您的数据”。我的建议是在建立数据之前先测试一下数据的不同方法。


进一步阅读

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


为什么我写这个答案

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

该答案的目的是帮助新用户理解迭代并不一定是解决每个问题的方法,并且可能存在更好,更快和更惯用的解决方案,值得您花时间探索它们。我并不是要发动迭代与向量化之战,而是希望在开发使用此库的问题的解决方案时通知新用户。


21
这是唯一针对大熊猫惯用技术的答案,使其成为此问题的最佳答案。学会正确的代码获得正确的 答案 (而不是错误的代码获得正确的答案 -即效率低下,无法缩放,太适合特定数据)是学习熊猫(以及一般数据)的重要组成部分。
LinkBerest

3
但是,我认为您对for循环不公平,因为它们在我的测试中仅比列表理解慢一点。诀窍是循环播放zip(df['A'], df['B'])而不是df.iterrows()
不朽之夜

2
@ImperishableNight一点也不;这篇文章的重点不是一般地谴责迭代-而是专门谴责的使用iterrows(),并在存在更好的替代方案时隐式谴责迭代。for循环本身是可以的,但是如果您要反复执行逐元素转换,则列表理解会更好。
cs95

1
@sdbbs,使用sort_values对数据进行排序,然后在结果上调用to_string()。
cs95

1
在“列表推导”下,“在多列上迭代”示例需要警告:DataFrame.values将每列转换为通用数据类型。 DataFrame.to_numpy()也这样做。幸运的是,我们可以使用zip任意数量的列。
David Wasserman

396

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

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

itertuples() 应该比 iterrows()

但是要注意,根据文档(目前为熊猫0.24.2):

  • Iterrows:dtype可能与每一行都不匹配

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

  • 行程:请勿修改行

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

    使用DataFrame.apply()代替:

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

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

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


4
有人在完成此线程后很长时间才读过它,这只是一个小问题:在效率方面df.apply()与itetuples相比如何?
劳尔·瓜里尼

4
注意:您也可以说类似for row in df[['c1','c2']].itertuples(index=True, name=None):在行迭代器中仅包括某些列的内容。
Brian Burns

12
相反getattr(row, "c1"),您可以使用row.c1
维珀尔

1
我大约90%的人确定,如果您使用getattr(row, "c1")而不是row.c1,则会失去的性能优势itertuples,并且如果您实际上需要通过字符串访问属性,则应该改用iterrows。
Noctiphobia

3
我偶然发现了这个问题,因为尽管我知道存在拆分应用组合,但我仍然确实需要遍历 DataFrame(如问题所述)。并非每个人都可以通过numba和来进行改进cython(同一文档说“首先在Python中进行优化总是值得”)。我写这个答案是为了帮助其他人避免(有时令人沮丧)问题,因为其他答案都没有提到这些警告。误导任何人或说“这是正确的事情”绝不是我的意图。我已经改善了答案。
viddik13 '19

201

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


12
这比将DataFrame转换为numpy数组(通过.values)并直接在该数组上进行操作要快吗?我有同样的问题,但最终转换为numpy数组,然后使用cython。
vgoklani 2012年

12
@vgoklani如果逐行迭代效率低下,并且您有一个非对象numpy数组,那么几乎可以肯定地使用原始numpy数组会更快,尤其是对于具有多行的数组。您应该避免重复执行行,除非绝对必要
Phillip Cloud

7
我对df.iterrows(),df.itertuples()和zip(df ['a'],df ['b'])的时间消耗做了一些测试,并将结果发布到另一个问题:stackoverflow.com/a/34311080/2142098
Richard Wong

154

虽然这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

5
两个示例中的大部分时间差异似乎是由于您似乎在为.iterrows()命令使用基于标签的索引,而为.itertuples()命令使用基于整数的索引。
亚历克斯(Alex)2015年

2
对于基于财务数据的数据帧(时间戳和4倍浮点数)而言,itertuples的速度比在我的计算机上迭代的速度快19,57倍。只有for a,b,c in izip(df["a"],df["b"],df["c"]:几乎一样快。
哈本2015年

7
您能解释一下为什么更快吗?
安倍·米斯勒

4
@AbeMiessler将iterrows()每行数据放入一个系列中,而itertuples()没有。
miradulo

3
注意,列的顺序实际上是不确定的,因为它df是根据字典创建的,因此row[1]可以引用任何列。事实证明,整数与浮点数列的时间大致相同。
布赖恩·伯恩斯

88

您还可以df.apply()用于遍历行并访问一个函数的多列。

docs:DataFrame.apply()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)

df ['price']是指数据框中的列名吗?我正在尝试从csv文件中的几列创建具有唯一值的字典。我使用您的逻辑来创建具有唯一键和值的字典,并得到一个错误,指出TypeError :(“'Series'对象是可变的,因此无法进行哈希处理”,在索引0'处发生)
SRS

代码: df ['Workclass'] = df.apply(lambda行:dic_update(row),axis = 1)行尾 id = 0 行尾 def dic_update(row):如果行不在dic中:dic [row] = id id = id + 1
SRS

没关系,我明白了。将函数调用行更改为df_new = df ['Workclass']。apply(相同)
SRS

2
将轴默认设置为0是最糟糕的
zthomas.nc

9
请注意,apply它不会对行“迭代”,而是逐行应用函数。上面的代码会,如果你真的不工作必要的迭代和的indeces,例如在不同行的比较值时(在这种情况下,你可以做什么,但迭代)。
gented '18 -4-4

82

您可以按以下方式使用df.iloc函数:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']

1
我知道应该避免这样做,而推荐使用iterrows或itetuples,但是知道为什么会很有趣。有什么想法吗?
rocarvaj

12
如果您要保留数据类型并按名称引用列,这是我所知道的唯一有效技术。 itertuples保留数据类型,但删除不喜欢的任何名称。 iterrows相反。
肯·威廉姆斯

6
花了几个小时试图研究熊猫数据结构的特质,以做一些简单而富有表现力的事情。这导致可读代码。
肖恩·安德森

虽然for i in range(df.shape[0])可能会稍微加快这种方法的速度,但它仍然比我的应用程序的上述iterrows()方法慢约3.5倍。
金·米勒

在大型Datafrmes上,这似乎更好,因为my_iter = df.itertuples()需要双倍的内存和大量的时间来复制它。相同的iterrows()
巴斯蒂安

33

我一直在寻找如何在行和列上进行迭代,因此在这里结束:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)

18

您可以编写自己的迭代器来实现 namedtuple

from collections import namedtuple

def myiter(d, cols=None):
    if cols is None:
        v = d.values.tolist()
        cols = d.columns.values.tolist()
    else:
        j = [d.columns.get_loc(c) for c in cols]
        v = d.values[:, j].tolist()

    n = namedtuple('MyTuple', cols)

    for line in iter(v):
        yield n(*line)

这可以直接与媲美pd.DataFrame.itertuples。我的目标是更高效地执行相同的任务。


对于具有我的功能的给定数据框:

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

或搭配pd.DataFrame.itertuples

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

全面测试
我们测试使所有列均可用并对其进行子集设置。

def iterfullA(d):
    return list(myiter(d))

def iterfullB(d):
    return list(d.itertuples(index=False))

def itersubA(d):
    return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))

def itersubB(d):
    return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='iterfullA iterfullB itersubA itersubB'.split(),
    dtype=float
)

for i in res.index:
    d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);

在此处输入图片说明

在此处输入图片说明


2
对于不想阅读代码的人:蓝线是intertuples,橙线是通过yield块的迭代器列表。interrows不进行比较。
James L.

18

如何有效地进行迭代?

如果确实需要迭代熊猫数据,则可能要避免使用iterrows()。有不同的方法,通常iterrows()远非最佳。itertuples()可以快100倍。

简而言之:

  • 通常使用df.itertuples(name=None)。特别是当您有固定数量的列且少于255列时。参见要点(3)
  • 否则,df.itertuples()除非您的列具有特殊字符(例如空格或'-'),否则请使用。参见要点(2)
  • 它可以使用itertuples()使用最后一个例子,即使你的数据帧有奇怪列。参见要点(4)
  • iterrows()当您无法使用以前的解决方案时使用。参见要点(1)

遍历pandas数据框中的行的不同方法:

生成具有一百万行四列的随机数据框:

    df = pd.DataFrame(np.random.randint(0, 100, size=(1000000, 4)), columns=list('ABCD'))
    print(df)

1)通常iterrows()很方便,但是该死的慢:

start_time = time.clock()
result = 0
for _, row in df.iterrows():
    result += max(row['B'], row['C'])

total_elapsed_time = round(time.clock() - start_time, 2)
print("1. Iterrows done in {} seconds, result = {}".format(total_elapsed_time, result))

2)默认itertuples()值已经快得多,但是它不适用于诸如以下的列名My Col-Name is very Strange(如果重复列或如果列名不能简单地转换为python变量名,则应避免使用此方法):

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row.B, row.C)

total_elapsed_time = round(time.clock() - start_time, 2)
print("2. Named Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

3)itertuples()使用name = None 的默认值甚至更快,但由于必须在每列中定义一个变量,因此并不十分方便。

start_time = time.clock()
result = 0
for(_, col1, col2, col3, col4) in df.itertuples(name=None):
    result += max(col2, col3)

total_elapsed_time = round(time.clock() - start_time, 2)
print("3. Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

4)最后,named itertuples()的速度比上一点慢,但是您不必为每列定义一个变量,它可以与诸如的列名一起使用My Col-Name is very Strange

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row[df.columns.get_loc('B')], row[df.columns.get_loc('C')])

total_elapsed_time = round(time.clock() - start_time, 2)
print("4. Polyvalent Itertuples working even with special characters in the column name done in {} seconds, result = {}".format(total_elapsed_time, result))

输出:

         A   B   C   D
0       41  63  42  23
1       54   9  24  65
2       15  34  10   9
3       39  94  82  97
4        4  88  79  54
...     ..  ..  ..  ..
999995  48  27   4  25
999996  16  51  34  28
999997   1  39  61  14
999998  66  51  27  70
999999  51  53  47  99

[1000000 rows x 4 columns]

1. Iterrows done in 104.96 seconds, result = 66151519
2. Named Itertuples done in 1.26 seconds, result = 66151519
3. Itertuples done in 0.94 seconds, result = 66151519
4. Polyvalent Itertuples working even with special characters in the column name done in 2.94 seconds, result = 66151519

本文是iterrows和itertuples之间非常有趣的比较


14

要循环一个中的所有行,dataframe您可以使用:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]

1
这是链接索引。我不建议这样做。
cs95

@ cs95您会推荐什么?
CONvid19 19:42

如果要执行此操作,请调用df.columns.get_loc以获取date列的整数索引位置(循环之外),然后在内部使用单个iloc索引调用。
cs95

14
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]

1
在大型数据框(例如,数百万行)上使用时,此选项的性能如何?
Bazyli Debowski

老实说,我不完全清楚,我认为与最佳答案相比,经过的时间大约是相同的,因为这两种情况都使用“ for”构造。但是在某些情况下,内存可能会有所不同。
Grag2015 '18

4
这是链接索引。不要使用这个!
cs95

7

有时一个有用的模式是:

# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
    print(row_dict)

结果是:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}

6

若要将a中的所有行循环dataframe方便地使用每行的值,可以将其转换为s。例如:namedtuplesndarray

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

遍历行:

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

结果是:

[ 1.   0.1]
[ 2.   0.2]

请注意,如果index=True所述索引被添加为元组的第一个元素,这可能是不期望的对某些应用。


5

有一种方法可以在返回DataFrame而不是Series的同时迭代引发行。我没有看到任何人提到您可以将index作为列表传递给要作为DataFrame返回的行:

for i in range(len(df)):
    row = df.iloc[[i]]

请注意双括号的用法。这将返回一个具有单行的DataFrame。


这对于排序后在数据框中获得第n大行非常有帮助。谢谢!
詹森·哈里森

3

对于查看和修改值,我将使用iterrows()。在for循环中,并通过使用元组拆包(请参见示例:)i, row,我row仅用于查看值,并在想要修改值时iloc方法一起使用。如先前的答案所述,您不应在此处修改要迭代的内容。

for i, row in df.iterrows():
    df_column_A = df.loc[i, 'A']
    if df_column_A == 'Old_Value':
        df_column_A = 'New_value'  

这里的rowin循环是该行的副本,而不是它的视图。因此,您不应编写类似的内容row['A'] = 'New_Value',它不会修改DataFrame。但是,您可以使用iloc指定DataFrame来完成工作。


2

我知道我要参加答疑会很晚,但是我只想添加到上述@ cs95的答案中,我认为这应该是公认的答案。在他的回答中,他表明,熊猫矢量化远胜过其他使用数据帧计算内容的熊猫方法。

我想补充一点,如果您首先将数据帧转换为numpy数组,然后使用向量化,它甚至比pandas数据帧向量化要快(而且还包括将其转换回数据帧系列的时间)。

如果在@ cs95的基准代码中添加以下功能,这将非常明显:

def np_vectorization(df):
    np_arr = df.to_numpy()
    return pd.Series(np_arr[:,0] + np_arr[:,1], index=df.index)

def just_np_vectorization(df):
    np_arr = df.to_numpy()
    return np_arr[:,0] + np_arr[:,1]

在此处输入图片说明


1

您还可以进行numpy索引以提高速度。对于某些应用程序,它并不是真正的迭代,但是比迭代好得多。

subset = row['c1'][0:5]
all = row['c1'][:]

您可能还需要将其转换为数组。这些索引/选择应该已经像Numpy数组一样起作用,但是我遇到了问题,需要进行强制转换

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file

1

有很多方法可以遍历pandas数据框中的行。一种非常简单直观的方法是:

df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
    # For printing the second column
    print(df.iloc[i,1])
    # For printing more than one columns
    print(df.iloc[i,[0,2]])

0

本示例使用iloc隔离数据帧中的每个数字。

import pandas as pd

 a = [1, 2, 3, 4]
 b = [5, 6, 7, 8]

 mjr = pd.DataFrame({'a':a, 'b':b})

 size = mjr.shape

 for i in range(size[0]):
     for j in range(size[1]):
         print(mjr.iloc[i, j])

0

某些库(例如,我使用的Java互操作库)要求每次将值连续传递一次,例如,如果是流数据。为了复制流式传输的性质,我逐一“流式传输”我的数据帧值,我写了下面的内容,它有时会派上用场。

class DataFrameReader:
  def __init__(self, df):
    self._df = df
    self._row = None
    self._columns = df.columns.tolist()
    self.reset()
    self.row_index = 0

  def __getattr__(self, key):
    return self.__getitem__(key)

  def read(self) -> bool:
    self._row = next(self._iterator, None)
    self.row_index += 1
    return self._row is not None

  def columns(self):
    return self._columns

  def reset(self) -> None:
    self._iterator = self._df.itertuples()

  def get_index(self):
    return self._row[0]

  def index(self):
    return self._row[0]

  def to_dict(self, columns: List[str] = None):
    return self.row(columns=columns)

  def tolist(self, cols) -> List[object]:
    return [self.__getitem__(c) for c in cols]

  def row(self, columns: List[str] = None) -> Dict[str, object]:
    cols = set(self._columns if columns is None else columns)
    return {c : self.__getitem__(c) for c in self._columns if c in cols}

  def __getitem__(self, key) -> object:
    # the df index of the row is at index 0
    try:
        if type(key) is list:
            ix = [self._columns.index(key) + 1 for k in key]
        else:
            ix = self._columns.index(key) + 1
        return self._row[ix]
    except BaseException as e:
        return None

  def __next__(self) -> 'DataFrameReader':
    if self.read():
        return self
    else:
        raise StopIteration

  def __iter__(self) -> 'DataFrameReader':
    return self

可以使用:

for row in DataFrameReader(df):
  print(row.my_column_name)
  print(row.to_dict())
  print(row['my_column_name'])
  print(row.tolist())

并保留要迭代的行的值/名称映射。显然,这比使用如上所述的apply和Cython慢​​很多,但是在某些情况下是必需的。


0

简而言之

  • 尽可能使用向量化
  • 如果操作无法向量化-使用列表推导
  • 如果您需要一个代表整个行的对象,请使用itertuples
  • 如果上述操作太慢-请尝试swifter.apply
  • 如果仍然太慢-请尝试Cython例程

详细资料 该视频中的

基准测试 熊猫DataFrame中行的迭代基准

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.