【问题标题】:Pandas TimeGrouper: Drop "non full groups"Pandas TimeGrouper:删除“非完整组”
【发布时间】:2015-03-20 02:47:36
【问题描述】:

我正在按某个频率对数据进行分组,但似乎 TimeGrouper 在右侧为一些“剩余”数据创建了最后一个组。

df.groupby([pd.TimeGrouper("2AS", label='left')]).sum()['shopping'].plot()

我预计数据会随着时间的推移相当稳定,但2013 的最后一个数据点下降了近一半。我希望这会发生,因为使用两年一次的分组,后半部分 (2014) 丢失了。

rolling_mean 允许center=True,这将把NaN/drop 余数放在左边和右边。 Grouper 有类似的功能吗? I couldn't find any on the manual,但也许有解决方法?

【问题讨论】:

    标签: python pandas statistics


    【解决方案1】:

    我认为这里的问题并不真正涉及 TimeGrouper 可用的选项,而是您希望如何处理不均匀的数据。你基本上有4个我能想到的选择:

    1) 删除足够的观察值(在开始或结束时),这样您就有了 2 年的观察值的倍数。

    2) 推断您的开始(或结束)时期,使其与具有完整数据的时期具有可比性。

    3) 根据少于 2 年的基础时间段将您的数据标准化为 2 年的总和。这种方法可以与其他两种方法结合使用。

    4) 不要使用 groupby 方法,只需做一个 rolling_sum。


    示例数据框:

    rng = pd.date_range('1/1/2010', periods=60, freq='1m')
    df = pd.DataFrame({ 'shopping' : np.random.choice(12,60) }, index=rng )
    

    我刚刚用从 1 月 1 日开始的 5 年数据创建了示例数据集,所以如果你每年都这样做,你就完成了。

    df.groupby([pd.TimeGrouper("AS", label='left')]).sum()['shopping']
    Out[206]: 
    2010-01-01    78
    2011-01-01    60
    2012-01-01    76
    2013-01-01    51
    2014-01-01    60
    Freq: AS-JAN, Name: shopping, dtype: int64
    

    这是表格形式的问题,前两组基于 2 年的数据,而第三组仅基于 1 年的数据。

    df.groupby([pd.TimeGrouper("2AS", label='left')]).sum()['shopping']
    Out[205]: 
    2010-01-01    138
    2012-01-01    127
    2014-01-01     60
    Freq: 2AS-JAN, Name: shopping, dtype: int64
    

    如果您采用上述方法(1),您只需要放弃一些观察。删除后面的观察并重新输入相同的命令非常容易。放弃较早的观察有点棘手,因为这样您的第一次观察不会在偶数年的 1 月 1 日开始,并且您会丢失自动标记等。这是一种方法,将删除第一年并保留最后 4 年,但您会丢失漂亮的标签(您可以与上面的年度数据进行比较以验证这是否正确):

    In [202]: df2 = df[12:]
    
    In [203]: df2['group24'] = (np.arange( len(df2) ) / 24 ).astype(int)
    
    In [204]: df2.groupby('group24').sum()['shopping']
    Out[204]: 
    group24
    0          136
    1          111
    

    或者,让我们尝试方法 (2),外推。为此,只需将 sum() 替换为 mean() 并乘以 24。对于上一期,这仅意味着我们假设 2014 年的 60 将等于 2015 年的另一个 60。这是否合理将是需要您做出判断,您可能希望用星号标记并将其称为估计值。

    df.groupby([pd.TimeGrouper("2AS")]).mean()['shopping']*24
    Out[208]: 
    2010-01-01    138
    2012-01-01    127
    2014-01-01    120
    Freq: 2AS-JAN, Name: shopping, dtype: float64
    

    另外请记住,这只是您可以在期末推断的一种简单(可能过于简单)的方法。这是否是最好的方法(或者推断是否有意义)是您根据情况做出的判断。

    接下来,您可以采用方法 (3) 并进行某种标准化。我不确定你到底想要什么,所以我只是勾勒出这些想法。如果您想显示两年的总和,您可以使用前面的示例,将“2AS”替换为“AS”,然后乘以 2。这基本上会使表格看起来不正确,但这是制作图表的一种非常简单的方法看起来不错。

    最后,只需使用滚动和:

    pd.rolling_sum(df.shopping,window=24)

    不能很好地表,但会很好地绘制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      • 2017-05-19
      相关资源
      最近更新 更多