【问题标题】:iterrows pandas get next rows valueiterrows pandas 获取下一行值
【发布时间】:2014-06-02 19:02:42
【问题描述】:

我在 pandas 中有一个 df

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

我想遍历 df 中的行。对于每一行我想要 rows value and next rows 值 类似的东西(它不起作用):

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']

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

【问题讨论】:

    标签: python pandas next


    【解决方案1】:

    首先,您的“混乱方式”是可以的,在数据​​框中使用索引没有任何问题,而且不会太慢。 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)
    

    当速度很关键时,您总是可以同时尝试并为代码计时。

    【讨论】:

    • 我相信第一个选项的第二行应该是:_, last = row_iterator.next()
    • 对于 Python3 的人们使用 next(row_iterator) 或 row_iterator__next__()
    • 在这个例子中,_, 做了什么?为什么我不能只做last = next(row_iterator)five operations 中的哪一个在这里执行?
    【解决方案2】:

    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 中的迭代行很慢,如果您能解释您要解决的问题是什么,也许我可以提出一些更好的方法。

    【讨论】:

    • 这很好。我正在研究与原始问题类似的问题,这完美地解决了我的问题。谢谢。
    • 在Python3中你不再需要导入izip——内置的zip提供了SO reference的功能
    • 直接链接到 Python3 itertools recipe
    【解决方案3】:

    我会使用 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
    

    上面的代码是这样工作的:

    第一步)使用移位功能

    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
    

    第 3 步)取消堆叠:

    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
    

    步骤 4) 删除 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
    

    步骤 5) 返回 DataFrame 的 Numpy 表示,并按值打印:

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

    产生:

    AA
    BB
    BB
    CC
    CC
    

    【讨论】:

    • 非常非常好!
    • 这个效果很好,谢谢。这条线df['value_1'] = df.value.shift(-1) 是我解决类似要求所需的全部内容。谢谢!
    【解决方案4】:

    这也可以通过izipping 带有自身偏移版本的数据帧(迭代器)来解决。

    当然索引错误不能通过这种方式重现。

    看看这个

    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
    

    【讨论】:

      【解决方案5】:

      答案的组合给了我一个非常快的运行时间。 使用 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]
      

      希望它会有所帮助。

      【讨论】:

        猜你喜欢
        • 2016-06-10
        • 2019-04-14
        • 2022-10-01
        • 2018-11-02
        • 1970-01-01
        • 2019-06-06
        • 2014-10-17
        • 1970-01-01
        • 2016-06-21
        相关资源
        最近更新 更多