【问题标题】:Pandas Grouper: how to use offset and origin to get a custom monthly frequency?Pandas Grouper:如何使用偏移量和原点来获得自定义的每月频率?
【发布时间】:2021-10-14 11:04:41
【问题描述】:

我想在自定义日期范围内对我的数据进行分组和汇总。我想按月范围分组,但从每个月的第 10 天开始和结束。 Pandas Grouper 中默认的freqMMS 仅允许每个月的第一天或最后一天。根据文档,我认为使用 offset 参数可以让我在每个月的第 10 天开始和结束,但它似乎没有效果。 origin 参数似乎也没有效果。请看下面的例子:

创建玩具数据框(df):

df = pd.DataFrame(columns=["date", "amount"], data=[["2021-01-01", 1],
                                                    ["2021-01-02", 1],
                                                    ["2021-01-20", 1],
                                                    ["2021-02-02", 1],
                                                    ["2021-02-11", 1],
                                                    ["2021-03-05", 1],
                                                    ["2021-03-27", 1],])
df["date"] = pd.to_datetime(df["date"])

df 现在看起来像:

    date       amount
0   2021-01-01   1
1   2021-01-02   1
2   2021-01-20   1
3   2021-02-02   1
4   2021-02-11   1
5   2021-03-05   1
6   2021-03-27   1

现在我尝试使用 offset 参数按自定义的每月范围进行分组。我希望它的范围是从每个月的第 10 天到下个月的第 9 天。另外,我希望在2021-01-05 开始我的分组,不管前几天。

df.groupby(pd.Grouper(key='date', freq="1MS", closed="left",
                      offset="10D", origin="2021-01-05")).sum()

预期输出:

           amount
date    
2021-01-10   2
2021-02-10   2
2021-03-10   1

实际输出:

           amount
date    
2021-01-01   3
2021-02-01   2
2021-03-01   2

如您所见,offsetorigin 参数似乎都没有被考虑在内!

编辑 1:This question 是相关的,因为最终目标相似,但没有询问 offsetorigin 的使用。此外,该问题的答案还不够充分。

编辑 2:删除了代码和输出的图像,并替换为文本代码。

【问题讨论】:

标签: python pandas group-by pandas-groupby


【解决方案1】:

几个月很难驯服...

您可以使用pd.DateOffsetpd.cut 使用以下方法:

start, end = df.date.iloc[0], df.date.iloc[-1]
ms1_d10 = pd.DateOffset(months=1, day=10)
bins = pd.date_range(start - ms1_d10, end + ms1_d10, freq=ms1_d10)
result = df.groupby(pd.cut(df.date, bins=bins)).sum()

使用数据框

df = pd.DataFrame(
    {"date": ["2021-01-01", "2021-01-02", "2021-01-10", "2021-02-02",
              "2021-02-11", "2021-03-05", "2021-03-27"],
     "amount": 1}
)
df.date = pd.to_datetime(df.date)

这导致

                          amount
date                            
(2020-12-10, 2021-01-10]       3
(2021-01-10, 2021-02-10]       1
(2021-02-10, 2021-03-10]       2
(2021-03-10, 2021-04-10]       1

如果你不喜欢你可以使用标签的间隔:

result = df.groupby(pd.cut(df.date, bins=bins, labels=bins[1:])).sum()
                     amount
date                       
2021-01-10 00:00:00       3
2021-02-10 00:00:00       1
2021-03-10 00:00:00       2
2021-04-10 00:00:00       1

【讨论】:

  • 这似乎完成了工作!谢谢蒂姆斯。我仍然对可以将Grouperoffsetorigin 参数一起使用的答案感兴趣,所以我给了你一个赞成票,但没有接受你的答案(至少现在还没有)。
  • @DataMan 感谢您的反馈!我在Grouper 上做了很多努力才能完成类似的事情——但无济于事。如果我错过了一些明显的东西,我很好奇自己。 (几个月是一件棘手的事情。我曾经非常沮丧,以至于我开始编写一个包含几个月的 timedelta 扩展类 - 只是为了在中途意识到 dateutils 已经有了一个很好的解决方案。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
相关资源
最近更新 更多