【问题标题】:Groupby with TimeGrouper 'backwards'Groupby 与 TimeGrouper '向后'
【发布时间】:2016-10-18 09:09:07
【问题描述】:

我有一个包含时间序列的DataFrame

rng = pd.date_range('2016-06-01', periods=24*7, freq='H')
ones = pd.Series([1]*24*7, rng)
rdf = pd.DataFrame({'a': ones})

最后一个条目是2016-06-07 23:00:00。我现在想按两天分组,基本上是这样的:

rdf.groupby(pd.TimeGrouper('2D')).sum()

但是,我想从最后一个数据点开始向后分组,所以不要得到这个结果:

            a
2016-06-01  48
2016-06-03  48
2016-06-05  48
2016-06-07  24

我更希望这样:

            a
2016-06-01  24
2016-06-03  48
2016-06-05  48
2016-06-07  48

当按'3D'分组时:

            a
2016-06-01  24
2016-06-04  72
2016-06-07  72

'4D' 分组时的预期结果是:

            a
2016-06-03  72
2016-06-07  96

我无法通过closedlabel 等的每一种组合来实现这一点。我能想到的。

我怎样才能做到这一点?

【问题讨论】:

    标签: python numpy pandas time-series


    【解决方案1】:

    由于问题现在侧重于按周分组,您可以简单地:

    rdf.resample('W-{}'.format(rdf.index[-1].strftime('%a')), closed='right', label='right').sum()
    

    您可以使用loffset 让它工作 - 至少在大多数时期(使用.resample()):

    for i in range(2, 7):
        print(i)
        print(rdf.resample('{}D'.format(i), closed='right', loffset='{}D'.format(i)).sum())
    
    2
                 a
    2016-06-01  24
    2016-06-03  48
    2016-06-05  48
    2016-06-07  48
    3
                 a
    2016-06-01  24
    2016-06-04  72
    2016-06-07  72
    4
                 a
    2016-06-01  24
    2016-06-05  96
    2016-06-09  48
    5
                  a
    2016-06-01   24
    2016-06-06  120
    2016-06-11   24
    6
                  a
    2016-06-01   24
    2016-06-07  144
    

    但是,您也可以创建自定义分组,在没有 TimeGrouper 的情况下计算正确的值,如下所示:

    days = rdf.index.to_series().dt.day.unique()[::-1]
    for n in range(2, 7):
        chunks = [days[i:i + n] for i in range(0, len(days), n)][::-1]
        grp = pd.Series({k: v for d in [zip(chunk, [idx] * len(chunk)) for idx, chunk in enumerate(chunks)] for k, v in d})
        rdf.groupby(rdf.index.to_series().dt.day.map(grp))['a'].sum()
    
     2
    groups
    0    24
    1    48
    2    48
    3    48
    Name: a, dtype: int64
    
     3
    groups
    0    24
    1    72
    2    72
    Name: a, dtype: int64
    
     4
    groups
    0    72
    1    96
    Name: a, dtype: int64
    
     5
    groups
    0     48
    1    120
    Name: a, dtype: int64
    
     6
    groups
    0     24
    1    144
    Name: a, dtype: int64
    

    【讨论】:

    • 谢谢!由于最后一个垃圾箱是我最重要的垃圾箱,因此我需要它非常可靠。奇怪,这似乎没有简单的解决方案。
    • 查看更新的解决方案,以可靠的方式计算组值,但不使用 TimeGrouper。
    【解决方案2】:

    由于我主要想按 7 天(也就是一周)分组,我现在使用这种方法来找到所需的垃圾箱:

    from pandas.tseries.offsets import Week
    
    # Let's not make full weeks
    hours = 24*6*4
    rng = pd.date_range('2016-06-01', periods=hours, freq='H')
    
    # Set week start to whatever the last weekday of the range is
    print("Last day is %s" % rng[-1])
    freq = Week(weekday=rng[-1].weekday())
    
    ones = pd.Series([1]*hours, rng)
    rdf = pd.DataFrame({'a': ones})
    rdf.groupby(pd.TimeGrouper(freq=freq, closed='right', label='right')).sum()
    

    这给了我想要的输出

    2016-06-25  96
    2016-07-02  168
    2016-07-09  168
    

    【讨论】:

    • 这可能也可以通过DateOffset 更通用地完成。
    猜你喜欢
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2017-11-24
    • 2013-01-12
    • 2014-10-22
    • 2017-06-28
    • 1970-01-01
    • 2017-08-16
    相关资源
    最近更新 更多