使用iterrows在pandas中获取下一行的值
我在pandas中有一个数据框(df)
import pandas as pd
df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])
我想要逐行遍历这个数据框。对于每一行,我想要这一行的值和下一行的值。想做成这样(但这个方法不行):
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 个回答
2
这个问题也可以通过将数据框(dataframe)和它自己偏移后的版本进行配对来解决,使用的是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
3
结合了几个答案后,我得到了一个运行速度非常快的方案。首先,我使用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]
希望这能帮到你。
10
我会这样使用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
下面是上面代码的工作原理:
第一步)使用shift函数
df['value_1'] = df.value.shift(-1)
print(df)
产生:
value value_1
0 AA BB
1 BB CC
2 CC NaN
第二步)转置:
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
15
在 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
中逐行迭代会比较慢。如果你能说说你想解决的问题是什么,也许我可以给你推荐一些更好的方法。
32
首先,你的“乱七八糟的方法”没问题,使用数据框中的索引是可以的,这样做不会太慢。其实,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)
当速度非常重要时,你可以尝试两种方法,然后测一下代码运行的时间。