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


当前回答

可能是最优雅的解决方案(但肯定不是最有效的):

for row in df.values:
    c2 = row[1]
    print(row)
    # ...

for c1, c2 in df.values:
    # ...

注意:

文档明确建议改用.to_numpy()在最坏的情况下,生成的NumPy数组将具有适合所有列的dtype对象首先有充分的理由不使用循环

尽管如此,我认为这个选项应该包含在这里,作为一个(人们应该认为)微不足道的问题的直接解决方案。

其他回答

首先考虑是否真的需要迭代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迭代文档。

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

简言之

如果可能,使用矢量化如果操作无法矢量化,请使用列表综合如果需要一个表示整个行的对象,请使用itert元组如果以上步骤太慢,请尝试快速应用如果速度仍然太慢,试试赛马拉松的套路

基准

更新:cs95更新了他的答案,包括简单的numpy矢量化。你可以简单地参考他的答案。


cs95表明,Pandas矢量化在使用数据帧计算数据方面远远优于其他Pandas方法。

我想补充一点,如果您首先将数据帧转换为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]

要循环数据帧中的所有行,可以使用:

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