熊猫时间序列重新采样,分箱似乎关闭

Posted

技术标签:

【中文标题】熊猫时间序列重新采样,分箱似乎关闭【英文标题】:Pandas time series resample, binning seems off 【发布时间】:2019-05-11 00:35:54 【问题描述】:

当我注意到这个奇怪的分箱时,我正在用我想知道的关于 pandas 的一些问题来回答另一个问题,时间序列重采样。

假设我有一个数据框,其中包含每日日期范围索引和一个我想要重新采样和求和的列。

index = pd.date_range(start="1/1/2018", end="31/12/2018") 
df = pd.DataFrame(np.random.randint(100, size=len(index)), 
                  columns=["sales"], index=index)

>>> df.head()
            sales
2018-01-01     66
2018-01-02     18
2018-01-03     45
2018-01-04     92
2018-01-05     76

现在我重新采样了一个月,一切看起来都很好:

>>>df.resample("1M").sum()

            sales
2018-01-31   1507
2018-02-28   1186
2018-03-31   1382
[...]
2018-11-30   1342
2018-12-31   1337

如果我尝试再采样几个月,尽管分箱开始出现问题。这在6M 中尤为明显

df.resample("6M").sum()                                                           
            sales
2018-01-31   1507
2018-07-31   8393
2019-01-31   7283

第一个 bin 跨越一个多月,最后一个 bin 跨一个月到未来。也许我必须设置closed="left" 以获得适当的限制:

df.resample("6M", closed="left").sum()                                            
            sales
2018-06-30   8090
2018-12-31   9054
2019-06-30     39

现在我在 2019 年有一个额外的 bin,其中包含 2018 年 12 月 31 日的数据...

这是否正常工作?我错过了我应该设置的任何选项吗?

编辑:这是我希望以六个月为间隔重新采样一年的输出,第一个间隔从 1 月 1 日到 6 月 30 日,第二个间隔从 7 月 1 日到 12 月 31 日。

df.resample("6M", closed="left").sum()                                            
            sales
2018-06-30   8090
2018-12-31   9093 # 9054 + 39

请注意,对于 6 月 30 日的数据会发生什么,这里也存在一些疑问,它是像我预期的那样进入第一个 bin 还是第二个 bin?我的意思是最后一个垃圾箱很明显,但所有垃圾箱都可能发生同样的情况。

【问题讨论】:

也许可以帮助this @jezrael 感谢简单地看了看,与closedlabelloffset 一起玩,但我认为没有办法获得我期望的行为...... 您能否补充质疑您的预期输出?我认为日期时间,如果可能的话也汇总数字 【参考方案1】:

M 时间偏移别名暗示month end frequency。 你需要的是6MS,它是月份开始频率的别名:

df.resample('6MS').sum()

导致

            sales
2018-01-01   8130
2018-07-01   9563
2019-01-01      0

df.groupby(pd.Grouper(freq='6MS')).sum() 也可以互换使用。


为了更加清楚,您可以直接比较范围:

>>> pd.date_range('2018-01-01', '2018-12-31', freq='6M')
DatetimeIndex(['2018-01-31', '2018-07-31'], dtype='datetime64[ns]', freq='6M')

>>> pd.date_range('2018-01-01', '2018-12-31', freq='6MS')
DatetimeIndex(['2018-01-01', '2018-07-01'], dtype='datetime64[ns]', freq='6MS')

【讨论】:

【参考方案2】:

添加np.random.seed(365) 来检查我们的输出。

print(df.resample("6M", kind='period').sum())

         sales
2018-01   8794
2018-07   9033

这对你有用吗?

【讨论】:

酷,我认为另一个答案解决了我的问题,但这对于我需要它的任务可能更有用,谢谢! 不知道它是怎么做的,但没关系。 2019 年的第一天仍然显示在另一个答案中。虽然是 0 当然,但它解释了分箱逻辑的错误所在:仅说明区间的哪一侧关闭是不够的,您还需要说明是否希望它在第一天开始一个月或最后一个月。使用"period" 可以解决所有问题,一切都按照您的预期进行,我更喜欢它,但它并不能解释我所询问的奇怪行为。还会更改索引类型。

以上是关于熊猫时间序列重新采样,分箱似乎关闭的主要内容,如果未能解决你的问题,请参考以下文章

熊猫时间序列重新采样结束给定的一天

熊猫数据框每天重新采样,没有日期时间索引

熊猫数据框每天重新采样,没有日期时间索引

在熊猫中重新采样时间序列

重新采样熊猫数据框并用零填充新行

熊猫重新采样时间序列数据 - 同一列上有多个 agg 函数?