熊猫日期时间周与预期不符

Posted

技术标签:

【中文标题】熊猫日期时间周与预期不符【英文标题】:Pandas datetime week not as expected 【发布时间】:2019-09-17 06:36:54 【问题描述】:

在使用 Pandas 日期时间时,我尝试按周和年对数据进行分组。但是,我注意到有些年份,一年的最后一天最终与同一年的第一周分组。

import pandas as pd
day_df = pd.DataFrame(index=pd.date_range('2016-01-01', '2020-12-31'))

for (week, year), subset in day_df.groupby([day_df.index.week, day_df.index.year]):
     if week == 1:
         print('Week:', subset.index.min(), subset.index.max())

Week: 1 2016-01-04 00:00:00 2016-01-10 00:00:00
Week: 1 2017-01-02 00:00:00 2017-01-08 00:00:00
Week: 1 2018-01-01 00:00:00 2018-12-31 00:00:00
Week: 1 2019-01-01 00:00:00 2019-12-31 00:00:00
Week: 1 2020-01-01 00:00:00 2020-01-05 00:00:00

对于 2018 年和 2019 年,一年的第一天最终与一年的最后一天归为一组!这种行为是预期的吗?为什么一年的最后一天是第一周?

我已经通过基本的if 语句获得了我想要的结果,但是这种week 行为似乎可能会导致问题,因为它是意料之外的。

这符合我对分组的预期:

for (week, year), subset in day_df.groupby([day_df.index.week, day_df.index.year]):
    # Prevent first week of year from including final days of same year
    if set(subset.index.month.unique()) == set([1, 12]):
        subset = subset.loc[subset.index.month == 1]
    if week == 1:
        print('Week:', week, subset.index.min(), subset.index.max())

Week: 1 2016-01-04 00:00:00 2016-01-10 00:00:00
Week: 1 2017-01-02 00:00:00 2017-01-08 00:00:00
Week: 1 2018-01-01 00:00:00 2018-01-07 00:00:00
Week: 1 2019-01-01 00:00:00 2019-01-06 00:00:00
Week: 1 2020-01-01 00:00:00 2020-01-05 00:00:00

【问题讨论】:

【参考方案1】:

这个问题的答案在于 .week() 是一个星期序数。 .week() 方法在文档中的最低定义为:

DatetimeIndex.week

一年中的第几周

周序号正式称为 ISO 周日期。可以在 python 3.7.3 日期时间文档中的date.isocalendar() 下找到关于它的更多说明。有关周序号如何工作的一般说明,您可以在***ISO week date 中找到完整的详细信息。

可以在EpochConverter.com 上找到 2019 年的周序号,它清楚地显示了一年中的第一天是 2018 年 12 月 31 日。

如果我们查看 2019 年的第 1 周,我们可以看到 12 月 31 日是第一天,并从 2019 年的第 1 周开始。因此,这实际上符合您在年初筛选器中包含的条件.

下面我们过滤 2018 年底和 2019 年初,看看 .week 做了什么。

day_df["ordinal"] = day_df.index.week
day_df["day_of_week"] = day_df.index.weekday
print(day_df.loc["2018-12-28":"2019-01-08"])



             ordinal  day_of_week
2018-12-28       52            4
2018-12-29       52            5
2018-12-30       52            6
2018-12-31        1            0
2019-01-01        1            1
2019-01-02        1            2
2019-01-03        1            3
2019-01-04        1            4
2019-01-05        1            5
2019-01-06        1            6
2019-01-07        2            0
2019-01-08        2            1

您需要添加一个月标准,以确保它是在一月份,正如您在上面的问题中发现的那样。这也有效。

for (week, month, year), subset in day_df.groupby(
    [day_df.index.week, day_df.index.month, day_df.index.year]
):
    if week == 1 and month == 1:
        print("Week:", subset.index.min(), subset.index.max())

如果您希望第一周从同一天开始,请使用[pandas.period.strftime()]5

%U 定义为

一年中的周数(星期日为一周的第一天),十进制数 [00,53]。新年前的所有日子 星期日被认为是在第 0 周。

对于您的数据框,如下所示:

day_df['date'] = day_df.index
day_df["day_name"] = day_df['date'].dt.day_name()
day_df['str_from_time'] = day_df['date'].apply(lambda x: x.strftime("%U"))
day_df.loc["2018-12-28":"2019-01-08",['ordinal', 'str_from_time', 'day_of_week', 'day_name']]

            ordinal str_from_time  day_of_week   day_name
2018-12-28       52            51            4     Friday
2018-12-29       52            51            5   Saturday
2018-12-30       52            52            6     Sunday
2018-12-31        1            52            0     Monday
2019-01-01        1            00            1    Tuesday
2019-01-02        1            00            2  Wednesday
2019-01-03        1            00            3   Thursday
2019-01-04        1            00            4     Friday
2019-01-05        1            00            5   Saturday
2019-01-06        1            01            6     Sunday
2019-01-07        2            01            0     Monday
2019-01-08        2            01            1    Tuesday

【讨论】:

这并不能完全解决我的问题。为什么一年中的最后一天会有第一周? 我已经更新了答案,希望能更好地回答您的问题。这是一个有趣的问题,感谢发帖,我学到了一些关于该方法的新信息。 感谢您的详尽回答。现在这确实回答了我的问题!

以上是关于熊猫日期时间周与预期不符的主要内容,如果未能解决你的问题,请参考以下文章

SQL between and 日期范围 筛选数据不符

熊猫:从日期时间索引合并日期和小时

将字符串日期时间转换为熊猫日期时间

加入带有日期范围的熊猫时间序列

如何格式化熊猫日期时间? [复制]

尽管是日期值,但使用显示日期时间的熊猫导入 excel 数据