如何在Pandas DataFrame中逐行迭代

如何在Pandas DataFrame中逐行迭代

技术背景

在数据处理和分析中,Pandas 是一个广泛使用的 Python 库,DataFrame 是 Pandas 中最常用的数据结构之一。有时我们需要对 DataFrame 中的每一行进行操作,因此需要逐行迭代。然而,直接使用迭代方法通常较慢,我们需要了解不同的迭代方法及其优缺点,以便根据具体情况选择合适的方法。

实现步骤

1. 使用 DataFrame.iterrows()

这是一个生成器,它会同时生成索引和行(作为 Series):

1
2
3
4
5
6
7
import pandas as pd

df = pd.DataFrame({'c1': [10, 11, 12], 'c2': [100, 110, 120]})
df = df.reset_index() # 确保索引与行数匹配

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

2. 使用 DataFrame.itertuples()

该方法通常比 iterrows() 更快:

1
2
for row in df.itertuples(index=True, name='Pandas'):
print(row.c1, row.c2)

3. 使用列表推导式

如果没有向量化解决方案,且性能不是非常关键时可以使用:

1
2
3
4
5
6
7
8
9
10
11
# 迭代一列
result = [f(x) for x in df['col']]

# 迭代两列
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]

# 迭代多列 - 相同数据类型
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]

# 迭代多列 - 不同数据类型
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]

4. 使用 DataFrame.apply()

1
2
3
4
def valuation_formula(x, y):
return x * y * 0.5

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

核心代码

以下是不同迭代方法的性能对比代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import pandas as pd
import numpy as np
import time

# 生成随机数据
df = pd.DataFrame(np.random.randint(0, 100, size=(1000000, 4)), columns=list('ABCD'))

# 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. 使用默认的 named itertuples()
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. 使用 nameless itertuples()
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. 使用 polyvalent itertuples()
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))

最佳实践

  • 优先使用向量化操作:许多基本操作和计算都可以通过向量化实现,如算术、比较、归约、重塑、连接和分组操作等。
  • 列表推导式:当没有向量化解决方案,且性能不是非常关键时,可以使用列表推导式。
  • itertuples():当需要单个对象表示整行时,使用 itertuples() 通常比 iterrows() 更快。
  • apply():当函数不能一次性处理整个 DataFrame/Series 时,可以使用 apply()
  • Cython 例程:如果对性能要求极高,可以考虑使用 Cython 编写代码。

常见问题

1. iterrows() 的性能问题

iterrows() 通常较慢,因为它会为每一行创建一个 Series 对象。尽量避免在处理大量数据时使用。

2. iterrows() 中修改行的问题

iterrows() 中修改行是不推荐的,因为迭代器可能返回的是副本而不是视图,修改可能无效。可以使用 DataFrame.apply() 代替。

3. itertuples() 的列名问题

itertuples() 中列名如果是无效的 Python 标识符、重复或以下划线开头,会被重命名为位置名称。当列数超过 255 时,会返回普通元组。


如何在Pandas DataFrame中逐行迭代
https://119291.xyz/posts/how-to-iterate-over-rows-in-a-pandas-dataframe/
作者
ww
发布于
2025年5月9日
许可协议