我有一个熊猫数据帧,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对象是什么,以及如何使用它。


当前回答

正如公认的答案所述,在行上应用函数的最快方法是使用矢量化函数,即所谓的NumPy-ufuncs(通用函数)。

但是,当您要应用的函数尚未在NumPy中实现时,应该怎么做?

好吧,使用numba的矢量化装饰器,您可以轻松地直接在Python中创建ufunc,如下所示:

from numba import vectorize, float64

@vectorize([float64(float64)])
def f(x):
    #x is your line, do something with it, and return a float

此函数的文档如下:创建NumPy通用函数

其他回答

您还可以使用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)

免责声明:尽管这里有很多答案建议不要使用迭代(循环)方法(我基本同意),但我仍然认为这是一种适用于以下情况的合理方法:

使用API中的数据扩展数据帧

假设您有一个包含不完整用户数据的大型数据帧。现在,您必须使用其他列来扩展此数据,例如,用户的年龄和性别。

这两个值都必须从后端API获取。我假设API不提供“批处理”端点(一次接受多个用户ID)。否则,您应该只调用一次API。

网络请求的成本(等待时间)远远超过了数据帧的迭代。我们讨论的是数百毫秒的网络往返时间,相比之下,使用迭代的替代方法可以忽略不计的小增益。

每行一个昂贵的网络请求

所以在这种情况下,我绝对倾向于使用迭代方法。尽管网络请求很昂贵,但可以保证对数据帧中的每一行只触发一次。以下是使用DataFrame.iterrows的示例:

实例

for index, row in users_df.iterrows():
  user_id = row['user_id']

  # Trigger expensive network request once for each row
  response_dict = backend_api.get(f'/api/user-data/{user_id}')

  # Extend dataframe with multiple data from response
  users_df.at[index, 'age'] = response_dict.get('age')
  users_df.at[index, 'gender'] = response_dict.get('gender')

正如公认的答案所述,在行上应用函数的最快方法是使用矢量化函数,即所谓的NumPy-ufuncs(通用函数)。

但是,当您要应用的函数尚未在NumPy中实现时,应该怎么做?

好吧,使用numba的矢量化装饰器,您可以轻松地直接在Python中创建ufunc,如下所示:

from numba import vectorize, float64

@vectorize([float64(float64)])
def f(x):
    #x is your line, do something with it, and return a float

此函数的文档如下:创建NumPy通用函数

首先考虑是否真的需要迭代DataFrame中的行。请参阅此答案以了解备选方案。

如果仍然需要迭代行,可以使用以下方法。请注意其他答案中未提及的一些重要注意事项。

DataFrame.iterrows()对于索引,df.iterrows()中的行:打印(行[“c1”],行[“c2”])DataFrame.itertuples()对于df.itertuples中的行(索引=True,名称=“标准”):打印(第c1行,第c2行)

itertples()应该比iterrows()快

但请注意,根据文件(熊猫目前为0.24.2):

iterrows:dtype可能在行与行之间不匹配

因为iterrows为每一行返回一个Series,所以它不会跨行保留数据类型(数据帧的数据类型跨列保留)。为了在遍历行时保留数据类型,最好使用itertples(),它返回值的namedtuples,通常比iterrows()快得多

iterrows:不修改行

您不应该修改正在迭代的内容。这并不能保证在所有情况下都有效。根据数据类型的不同,迭代器返回的是副本而不是视图,写入它不会产生任何影响。

请改用DataFrame.apply():

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

迭代:

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

有关详细信息,请参阅panda迭代文档。

最简单的方法是使用apply函数

def print_row(row):
   print row['c1'], row['c2']

df.apply(lambda row: print_row(row), axis=1)