【问题标题】:Pandas: groupby forward fill with datetime indexPandas:使用日期时间索引进行分组前向填充
【发布时间】:2016-11-30 12:53:18
【问题描述】:

我有一个包含两列的数据集:公司和价值。
它有一个日期时间索引,其中包含重复项(同一天,不同的公司有不同的值)。这些值缺少数据,所以我想用同一家公司的前一个数据点转发填充缺失的数据。

但是,我似乎找不到一个好方法来做到这一点,而不会遇到奇怪的 groupby 错误,这表明我做错了什么。

玩具数据:

a = pd.DataFrame({'a': [1, 2, None], 'b': [12,None,14]})
a.index = pd.DatetimeIndex(['2010', '2011', '2012'])  
a = a.unstack() 
a = a.reset_index().set_index('level_1') 
a.columns = ['company', 'value'] 
a.sort_index(inplace=True)

尝试的解决方案(无效:ValueError: cannot reindex from a duplicate axis):

a.groupby('company').ffill() 
a.groupby('company')['value'].ffill() 
a.groupby('company').fillna(method='ffill')

Hacky 解决方案(提供了预期的结果,但显然只是一个丑陋的解决方法):

a['value'] = a.reset_index().groupby(
    'company').fillna(method='ffill')['value'].values

这可能有一种简单而优雅的方法,这在 Pandas 中是如何执行的?

【问题讨论】:

    标签: python datetime pandas group-by missing-data


    【解决方案1】:

    我喜欢使用堆叠和拆解。在这种情况下,它要求我在索引后面附加'company'

    a.set_index('company', append=True).unstack().ffill() \
                                       .stack().reset_index('company')
    


    时间

    结论@Psidom 的解决方案在这两种情况下效果最佳。

    玩具数据

    更大的玩具

    np.random.seed([3,1415])
    n = 10000
    a = pd.DataFrame(np.random.randn(n, 10),
                     pd.date_range('2014-01-01', periods=n, freq='H', name='Time'),
                     pd.Index(list('abcdefghij'), name='company'))
    
    a *= np.random.choice((1, np.nan), (n, 10), p=(.6, .4))
    
    a = a.stack(dropna=False).rename('value').reset_index('company')
    

    【讨论】:

      【解决方案2】:

      您可以将'company' 添加到索引中,使其唯一,并通过groupby 做一个简单的ffill

      a = a.set_index('company', append=True)
      a = a.groupby(level=1).ffill()
      

      如有必要,您可以在此处使用reset_index 将索引恢复为刚刚的日期。我建议将 'company' 保留为索引的一部分(或者只是将其添加到索引中),这样您的索引将保持唯一:

      a = a.reset_index(level=1)
      

      【讨论】:

        【解决方案3】:

        一种方法是使用transform 函数在分组后填充value 列:

        import pandas as pd
        a['value'] = a.groupby('company')['value'].transform(lambda v: v.ffill())
        
        a
        #          company  value
        #level_1        
        #2010-01-01      a    1.0
        #2010-01-01      b   12.0
        #2011-01-01      a    2.0
        #2011-01-01      b   12.0
        #2012-01-01      a    2.0
        #2012-01-01      b   14.0
        

        为了比较,原始数据框如下所示:

        #            company    value
        #level_1        
        #2010-01-01        a      1.0
        #2010-01-01        b     12.0
        #2011-01-01        a      2.0
        #2011-01-01        b      NaN
        #2012-01-01        a      NaN
        #2012-01-01        b     14.0
        

        【讨论】:

        • 我发现a['value'] = a.groupby('company')['value'].transform(lambda v: v.ffill())a['value'] = a.groupby('company')['value'].ffill() 之间的结果没有差异
        猜你喜欢
        • 2020-01-02
        • 1970-01-01
        • 2015-03-27
        • 1970-01-01
        • 2021-06-21
        • 2021-07-14
        • 2021-02-18
        • 1970-01-01
        相关资源
        最近更新 更多