为什么 W-DAY 在 Pandas 中的表现令人困惑?

rlm*_*lms 6 python datetime pandas

等的行为freq = "W-SUN"似乎令人困惑且不一致。例如,d.date_range(pd.Timestamp('2019-07-09'), pd.Timestamp('2019-11-11'), freq='W-SUN')生成一系列星期日,但pd.Index([pd.Timestamp('2019-07-09')]).to_period('W-SUN').to_timestamp()生成星期一。这里发生了什么?

出现这种情况是因为我有一个日期索引,我想将其舍入到某个频率,同时还生成date_range具有相同频率和相位的日期索引。看起来应该适用index.to_period(freq).to_timestamp()于此pd.date_range(start, end, freq=freq),但当 freq 为 时则不然"W-DAY"

ASG*_*SGM 6

这有点违反直觉,但逻辑如下。当您使用 时.to_period(),Pandas 会计算您提供的日期所在的时间段。Pandas 计算该周期的方式是找到与您指定的频率相匹配的第二天,并将该周期向后延伸以包括您选择的日期。换句话说,该期间是包含结束的,而不是包含开始的

要查找给定星期二的星期日锚定周,它会查找该星期二之后的下一个星期日并添加前六天。但是,当您转换为时间戳时,它会选择该时间段的第一天,在本例中为星期一。如果您询问星期日的星期日锚定时段,它会给您当天加上前六天,而不是接下来的六天。

如果您希望经期在一周中的某一天开始而不是结束,只需将频率字符串设置为前一天即可。在你的情况下,pd.Index([pd.Timestamp('2019-07-09')]).to_period('W-SAT').to_timestamp()应该可以解决问题。


一些希望有帮助的演示:

pd.Index([pd.Timestamp('2019-07-09')]).to_period('W-SUN')给出:

PeriodIndex(['2019-07-08/2019-07-14'], dtype='period[W-SUN]', freq='W-SUN
Run Code Online (Sandbox Code Playgroud)

请注意,该时段于周日结束。当您运行时,pd.Index([pd.Timestamp('2019-07-09')]).to_period('W-SUN').to_timestamp()它会显示该期间的第一天:

DatetimeIndex(['2019-07-08'], dtype='datetime64[ns]', freq=None)
Run Code Online (Sandbox Code Playgroud)

您可以通过运行以下命令来观察如何选择日期:

for f in ['W-SUN', 'W-MON', 'W-TUE', 'W-WED', 'W-THU', 'W-FRI', 'W-SAT']:
    print(f, pd.Index([pd.Timestamp('2019-07-09')]).to_period(f))
Run Code Online (Sandbox Code Playgroud)

这使:

PeriodIndex(['2019-07-08/2019-07-14'], dtype='period[W-SUN]', freq='W-SUN')
PeriodIndex(['2019-07-09/2019-07-15'], dtype='period[W-MON]', freq='W-MON')
PeriodIndex(['2019-07-03/2019-07-09'], dtype='period[W-TUE]', freq='W-TUE')
PeriodIndex(['2019-07-04/2019-07-10'], dtype='period[W-WED]', freq='W-WED')
PeriodIndex(['2019-07-05/2019-07-11'], dtype='period[W-THU]', freq='W-THU')
PeriodIndex(['2019-07-06/2019-07-12'], dtype='period[W-FRI]', freq='W-FRI')
PeriodIndex(['2019-07-07/2019-07-13'], dtype='period[W-SAT]', freq='W-SAT')
Run Code Online (Sandbox Code Playgroud)

请注意,所选周期的开始在中间跳跃,但逻辑保持一致。