MultiIndexed DataFrame中的前向填充日期

时间:2014-07-17 18:11:17

标签: python pandas

我有一个带有MultiIndex的PANDAs DataFrame,其中一个级别代表一年:

import pandas as pd
df = pd.DataFrame(dict(A = ['foo', 'foo', 'bar', 'bar', 'bar', 'bar'],
                       B = ['white', 'black', 'white', 'white', 'black', 'black'],
                       year = [1990, 1992, 1990, 1992, 1991, 1992],
                       value = [3.14, 1.20, 4.56, 6.79, 0.01, 0.02]))

df = df.set_index(['A', 'B', 'year'])

我想转发填充值,但仅适用于每个组中的间隔年份(由A和B的交互定义)。这是输入:

                value
A   B     year       
foo white 1990   3.14
    black 1992   1.20
bar white 1990   4.56
          1992   6.79
    black 1991   0.01
          1992   0.02

这是所需的输出,还有一行:

                value
A   B     year       
foo white 1990   3.14
    black 1992   1.20
bar white 1990   4.56
          1991   4.56  <-- new forward-filled value
          1992   6.79
    black 1991   0.01
          1992   0.02

我如何简洁有效地完成这项工作?我尝试过使用groupbyapply的组合,但我是PANDAS的新手并继续抛出异常。

以下是我如何天真地接近问题的一个例子:

def ffill_years(df):
    df.reset_index(['A', 'B'])  # drop all but 'year'
    year_range = range(df['year'].min(), df['year'].max())
    df.reindex(pd.Series(years)).fillna("ffill")
    return df

df.groupby(level=['A', 'B']).apply(ffill_years)

当然这不起作用。任何和所有提示赞赏!

1 个答案:

答案 0 :(得分:3)

你非常接近 - 一些小改变:

  1. reset_index无法正常运作
  2. 无法按名称引用索引,需要使用.index
  3. 您的范围需要+1以包含端点
  4. reindex也不是就地
  5. fillna的第一个参数是填充值,请使用关键字method
  6. 见下文:

    def ffill_years(df):
        df = df.reset_index(['A','B'])  # drop all but 'year'
        year_range = range(df.index.min(), df.index.max() + 1)
    
        df = df.reindex(pd.Series(year_range)).fillna(method='ffill')
        return df
    

    结果

    In [209]: df.groupby(level=['A','B']).apply(ffill_years)
    Out[209]: 
                      A      B  value
    A   B     year                   
    bar black 1991  bar  black   0.01
              1992  bar  black   0.02
        white 1990  bar  white   4.56
              1991  bar  white   4.56
              1992  bar  white   6.79
    foo black 1992  foo  black   1.20
        white 1990  foo  white   3.14