重采样时的时间戳分箱机制

Posted

技术标签:

【中文标题】重采样时的时间戳分箱机制【英文标题】:timestamp binning mechanics when resampling 【发布时间】:2022-01-22 22:30:29 【问题描述】:

我不太清楚DataFrame.resample 中的 bin-membership 是如何确定的。

示例/实际输出:

>>> df = pd.DataFrame(index=pd.date_range(start='2021-04-21 01:00:00', end='2021-04-28 01:00', freq='1d'), data=[1]*8)
>>> df
                     0
2021-04-21 01:00:00  1
2021-04-22 01:00:00  1
2021-04-23 01:00:00  1
2021-04-24 01:00:00  1
2021-04-25 01:00:00  1
2021-04-26 01:00:00  1
2021-04-27 01:00:00  1
2021-04-28 01:00:00  1
>>> df.resample(rule='7d', origin='2021-04-29 00:00:00', closed='right', label='right').sum() 
            0
2021-04-22  2
2021-04-29  6

预期输出:

            0
2021-04-22  1
2021-04-29  7

推理:

我希望 pandas 会创建两个垃圾箱

(2021-04-15 00:00:00, 2021-04-22 00:00:00]
(2021-04-22 00:00:00, 2021-04-29 00:00:00]

时间戳2021-04-21 01:00:00 落入第一个 bin,而2021-04-22 01:00:00 和其余时间戳应落入第二个 bin。


编辑:我刚刚意识到使用 24*7=168 小时而不是 7 天会产生预期的结果。为什么?!

>>> df.resample(rule='168h', origin='2021-04-22 00:00:00', closed='right', label='right').sum() 
            0
2021-04-22  1
2021-04-29  7

我正在使用熊猫1.3.5

【问题讨论】:

我昨天的例子没有说服你? :) @Corralien 不完全,我不想在 cmets 中用进一步的后续问题来纠缠你。 【参考方案1】:

来自source code,我添加了一个调试行来理解

def _get_time_bins(self, ax: DatetimeIndex):

    # XXX: Debug - pandas/core/resample.py#L1630
    print(f"binner: binner\nbins: bins\nlabels: labels\nbin_edges: bin_edges")

    return binner, bins, labels

你的尝试:

>>> df.resample(rule='7d', origin='2021-04-29 00:00:00', closed='right', label='right').sum()

# Debug
binner: DatetimeIndex(['2021-04-15', '2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='7D')
bins: [2 8]
labels: DatetimeIndex(['2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='7D')
bin_edges: [1618531199999999999 1619135999999999999 1619740799999999999]

# Result
            0
2021-04-22  2
2021-04-29  6

要获得预期的结果:

>>> df.resample(rule='7d', origin='2021-04-29 00:00:00', closed='left', label='right').sum()

# Debug
binner: DatetimeIndex(['2021-04-15', '2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='7D')
bins: [1 8]
labels: DatetimeIndex(['2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='7D')
bin_edges: [1618444800000000000 1619049600000000000 1619654400000000000]

# Result
            0
2021-04-22  1
2021-04-29  7

我刚刚意识到使用 24*7=168 小时而不是 7 天会产生预期的结果。为什么?!

>>> df.resample(rule='168h', origin='2021-04-22 00:00:00', closed='right', label='right').sum()

# Debug
binner: DatetimeIndex(['2021-04-15', '2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='168H')
bins: [1 8]
labels: DatetimeIndex(['2021-04-22', '2021-04-29'], dtype='datetime64[ns]', freq='168H')
bin_edges: [1618444800000000000 1619049600000000000 1619654400000000000]

# Result:
            0
2021-04-22  1
2021-04-29  7

事实上,我认为 Pandas 一开始会根据规则'D''H' 中的单位截断日期时间。我想为什么“7D”和“168H”的行为不同。也许你应该向 github 提出一个问题。

【讨论】:

是的,我不明白为什么时间戳在被分类到正确的 bin 之前被截断。 github.com/pandas-dev/pandas/issues/44996

以上是关于重采样时的时间戳分箱机制的主要内容,如果未能解决你的问题,请参考以下文章

求助ArcGIS高手!!!重采样和矢量化啥关系?

如何使用音频重采样器对 IF 信号进行重采样

音频重采样

音频重采样实现原理

ArcGIS栅格分辨率重采样求助

重采样上采样下采样