iterrows pandas获取下一行的值

44

我有一个Pandas的数据框。

import pandas as pd
df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])

我想在df中迭代行。对于每一行,我想要当前行的值和下一行的值 类似以下方式(但不起作用):
for i, row in df.iterrows():
     print row['value']
     i1, row1 = next(df.iterrows())
     print row1['value']

作为结果,我想要的是
'AA'
'BB'
'BB'
'CC'
'CC'
*Wrong index error here  

目前我有一种混乱的方法来解决这个问题。
for i in range(0, df.shape[0])
   print df.irow(i)['value']
   print df.irow(i+1)['value']

有没有更有效的方法来解决这个问题?
5个回答

33

首先,你的"混乱方式"是可以的,使用数据帧中的索引没有任何问题,这不会太慢。 iterrows() 本身并不是非常快速。

一个可以工作的第一个想法版本将是:

row_iterator = df.iterrows()
_, last = row_iterator.next()  # take first item from row_iterator
for i, row in row_iterator:
    print(row['value'])
    print(last['value'])
    last = row
第二种方法可以做类似的事情,将一个索引保存到数据框中:
last = df.irow(0)
for i in range(1, df.shape[0]):
    print(last)
    print(df.irow(i))
    last = df.irow(i)

当速度至关重要时,您可以尝试两种方法并计时代码。


4
我认为第一选项的第二行应该改为: _, last = row_iterator.next() - maxliving
11
对于Python3用户,请使用next(row_iterator)或row_iterator__next__()。 - Sebastian Zaba
2
在这个例子中,_, 有什么作用?为什么我不能只写 last = next(row_iterator),而是要用到五种操作中的哪一种呢?请参考 five operations - Scott
"_" 是一个有效的标识符名称,甚至可以单独使用。实际上,它是一个毫无意义的名称,人们常常使用它来表示该值未被使用。你不能只做你所要求的,因为这个迭代器返回一个需要解包的元组。 - undefined

16

itertools 文档中有一个 pairwise() 函数的示例:

from itertools import tee, izip
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

import pandas as pd
df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])

for (i1, row1), (i2, row2) in pairwise(df.iterrows()):
    print i1, i2, row1["value"], row2["value"]

这是输出结果:
0 1 AA BB
1 2 BB CC

但是,我认为在DataFrame中遍历行很慢。如果您能解释一下您想要解决的问题,也许我可以建议一些更好的方法。


这非常好。我正在解决一个类似于原始问题的问题,这个解决方案完美地解决了我的问题。谢谢。 - Eric D. Brown D.Sc.
1
在Python3中,您不再需要导入izip - 内置的zip提供了相同的功能SO参考 - tatlar
1
Python3 itertools recipe 的直接链接。 - XoXo

11

我会按照以下方式使用shift()函数:

df['value_1'] = df.value.shift(-1)
[print(x) for x in df.T.unstack().dropna(how = 'any').values];

生产

AA
BB
BB
CC
CC

以下是上述代码的工作原理:

步骤1)使用shift函数

df['value_1'] = df.value.shift(-1)
print(df)

产生

value value_1
0    AA      BB
1    BB      CC
2    CC     NaN

步骤2)转换:

df = df.T
print(df)

生成:

          0   1    2
value    AA  BB   CC
value_1  BB  CC  NaN

步骤三)解除堆叠:

df = df.unstack()
print(df)
产生:
0  value       AA
   value_1     BB
1  value       BB
   value_1     CC
2  value       CC
   value_1    NaN
dtype: object

第四步) 删除NaN值

df = df.dropna(how = 'any')
print(df)

输出:

0  value      AA
   value_1    BB
1  value      BB
   value_1    CC
2  value      CC
dtype: object

步骤五)返回DataFrame的Numpy表示,并逐个打印值:

df = df.values
[print(x) for x in df];

生成:

AA
BB
BB
CC
CC

这个很好用,谢谢。这一行代码 df['value_1'] = df.value.shift(-1) 就是我解决类似需求所需要的全部内容。谢谢! - Roan

3

这可以通过使用自身的偏移版本与数据帧(迭代器)进行izip解决。

当然,这种方法无法复制索引错误。

看看这个:

import pandas as pd
from itertools import izip

df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])   

for id1, id2 in izip(df.iterrows(),df.ix[1:].iterrows()):
    print id1[1]['value']
    print id2[1]['value']

这提供了

AA
BB
BB
CC

2
一系列答案的结合使我获得了非常快的运行时间。 使用shift方法创建下一行值的新列, 然后像@alisdt一样使用row_iterator函数, 但我将其从iterrows更改为itertuples,速度提高了100倍。
我的脚本用于迭代不同长度的数据框中的重复项,并为每个重复项添加一秒钟,以使它们都是唯一的。
# create new column with shifted values from the departure time column
df['next_column_value'] = df['column_value'].shift(1)
# create row iterator that can 'save' the next row without running for loop
row_iterator = df.itertuples()
# jump to the next row using the row iterator
last = next(row_iterator)
# because pandas does not support items alteration i need to save it as an object
t = last[your_column_num]
# run and update the time duplications with one more second each
for row in row_iterator:
    if row.column_value == row.next_column_value:
         t = t + add_sec
         df_result.at[row.Index, 'column_name'] = t
    else:
         # here i resetting the 'last' and 't' values
         last = row
         t = last[your_column_num]

希望这能帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接