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