Python Pandas 遍历行并访问列名

Posted

技术标签:

【中文标题】Python Pandas 遍历行并访问列名【英文标题】:Python Pandas iterate over rows and access column names 【发布时间】:2017-09-23 00:17:57 【问题描述】:

我正在尝试遍历 Python Pandas 数据框的行。在数据框的每一行中,我试图通过列名来引用一行中的每个值。

这是我所拥有的:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(10,4),columns=list('ABCD'))
print df
          A         B         C         D
0  0.351741  0.186022  0.238705  0.081457
1  0.950817  0.665594  0.671151  0.730102
2  0.727996  0.442725  0.658816  0.003515
3  0.155604  0.567044  0.943466  0.666576
4  0.056922  0.751562  0.135624  0.597252
5  0.577770  0.995546  0.984923  0.123392
6  0.121061  0.490894  0.134702  0.358296
7  0.895856  0.617628  0.722529  0.794110
8  0.611006  0.328815  0.395859  0.507364
9  0.616169  0.527488  0.186614  0.278792

我使用this approach 进行迭代,但它只提供了部分解决方案 - 在每次迭代中选择一行后,如何通过列名访问行元素? p>

这是我想要做的:

for row in df.iterrows():
    print row.loc[0,'A']
    print row.A
    print row.index()

我的理解是该行是 Pandas series。但是我没有办法索引到系列中。

是否可以在遍历行的同时使用列名?

【问题讨论】:

row 在你的例子中不是一个系列,它应该是一个元组。但是如果你这样做for idx, row in df.iterrows()row['A'] 应该可以正常工作吗? 这就是我所缺少的!谢谢。 大多数使用 pandas 的数值运算都可以向量化——这意味着它们比传统迭代要快得多。 OTOH,某些操作(例如字符串和正则表达式)本质上很难矢量化。在这种情况下,了解 如何 循环数据非常重要。有关何时以及如何循环数据的更多信息,请阅读For loops with Pandas - When should I care?。 【参考方案1】:

我也喜欢itertuples()

for row in df.itertuples():
    print(row.A)
    print(row.Index)

由于 row 是一个命名元组,如果您要访问每一行的值,这应该MUCH更快

速度跑:

df = pd.DataFrame([x for x in range(1000*1000)], columns=['A'])
st=time.time()
for index, row in df.iterrows():
    row.A
print(time.time()-st)
45.05799984931946

st=time.time()
for row in df.itertuples():
    row.A
print(time.time() - st)
0.48400020599365234

【讨论】:

谢谢!我认为这实际上是我的想法(但不记得了)。它更实用(因为不需要idx,就像必须enumerate 一个列表)。因为我要求iterrows(),所以我会选择那个答案。但如果我记得,这就是我会使用的。 print(row.Index) 结果:AttributeError: 'tuple' object has no attribute 'Index' @kiltek 你用过itertuples(index=False) 吗?如果没有,我需要一些代码来找出问题所在 @WR 这应该是公认的答案。是up to 50x faster。 据我了解,如果列数大于255,则返回的元组没有命名。有没有办法覆盖它并为〜3000列生成命名元组?我想最终获取那些满足条件的列名。 @史蒂文G【参考方案2】:

iterrows() 中的项目不是一个系列,而是一个 (index, Series) 的元组,因此您可以像这样在 for 循环中解包该元组:

for (idx, row) in df.iterrows():
    print(row.loc['A'])
    print(row.A)
    print(row.index)

#0.890618586836
#0.890618586836
#Index(['A', 'B', 'C', 'D'], dtype='object')

【讨论】:

@StevenG 是的。这就是我想说的。我想如果我们说(索引,系列)会更清楚。 按照第二个答案中的建议使用 itertuples() ...如果您使用的是大型数据框,intertuples 会快很多【参考方案3】:

如何高效迭代

如果您确实需要迭代 Pandas 数据框,您可能希望避免使用 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) 使用 name=None 的默认 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) 最后,命名为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

This article is a very interesting comparison between iterrows and itertuples

【讨论】:

这应该是公认的答案【参考方案4】:

这并不像我希望的那样简单。您需要使用 enumerate 来跟踪您有多少列。然后使用该计数器查找列的名称。接受的答案没有向您展示如何动态访问列名。

for row in df.itertuples(index=False, name=None):
    for k,v in enumerate(row):
        print("column: 0".format(df.columns.values[k]))
        print("value: 0".format(v)

【讨论】:

【参考方案5】:
for i in range(1,len(na_rm.columns)):
           print ("column name:", na_rm.columns[i])

输出:

column name: seretide_price
column name: symbicort_mkt_shr
column name: symbicort_price

【讨论】:

写的太没用了,for循环可以直接在columns列表上迭代。

以上是关于Python Pandas 遍历行并访问列名的主要内容,如果未能解决你的问题,请参考以下文章

遍历 pandas 行并根据其他列中的值设置列值

遍历 pandas 数据框中的行并匹配列表中的元组并创建一个新的 df 列

循环遍历 pandas 列名以创建列表

pandas.DataFrame.loc好慢,怎么遍历访问DataFrame比较快

pandas.DataFrame.loc好慢,怎么遍历访问DataFrame比较快

pandas.DataFrame.loc好慢,怎么遍历访问DataFrame比较快