Pandas按每6个月频率生成以1月/6月为基准的日期范围

1 投票
3 回答
48 浏览
提问于 2025-04-14 17:57

我想用pandas的 date_range 来获取两个时间之间的所有日期,格式是“YYYY-01-01”和“YYYY-06-01”。

我原以为可以这样做:

pd.date_range("2023-01-05", "2024-12-01", freq="6MS-JAN")

但看起来这样用是行不通的。有没有其他简单的方法可以通过freq参数来实现呢?

根据我上面提到的开始和结束时间,我想要的日期是“2023-06-01”、“2024-01-01”和“2024-06-01”。

当然,我可以用一个循环来获取我想要的日期,但我想知道有没有更简单的方法。

谢谢!

3 个回答

1

如果你想要获取一个从一月或六月开始、每六个月一次的日期范围,你可以使用 pd.date_range 来实现。不过,不要试图用 freq 参数来设置一个自定义的起始点,而是根据需要手动调整开始日期,然后使用六个月的频率('6M')。接着,再筛选出只保留一月和六月的日期。

不过,当你在 pd.date_range 中使用 '6M' 时,通常日期不会完全对齐到每个月的开始,所以更可靠的方法是使用 '6MS' 作为频率,同时如果初始日期没有对齐到你想要的那样,稍微做一些调整。

下面是一种实现的方法:

import pandas as pd

def generate_custom_range(start, end):
   # Adjust start date to the next occurrence of January or June
   if 1 <= start.month < 6 and start.day > 1:
      start = pd.Timestamp(year=start.year, month=6, day=1)
   elif start.month >= 6 and start.day > 1:
      start = pd.Timestamp(year=start.year  + 1, month=1, day=1)
   # Generate the date range
   dates = pd.date_range(start, end, freq='6MS')
   return dates

使用示例:

start_date = "2023-01-05"
end_date = "2024-12-01"

start = pd.to_datetime(start_date)
end = pd.to_datetime(end_date)

dates = generate_custom_range(start, end)
print(dates)

示例结果:

DatetimeIndex(['2023-06-01', '2023-12-01', '2024-06-01', '2024-12-01'], dtype='datetime64[ns]', freq='6MS')
1

试试这个:

import pandas as pd
dates = pd.date_range("2023-05-01", "2024-01-01", freq='MS')
months = dates.month # Store all months
dates = dates[(months == 6) | (months == 1)] # Filter dates
dates
1

在你的情况中,你可以使用 freq,但前提是要有一个可以锚定的频率。

比如说,如果你想要获取所有的季度数据,你可以这样做:

pd.date_range('2023-01-05', '2024-12-01', freq='QS-DEC')
# DatetimeIndex(['2023-03-01', '2023-06-01', '2023-09-01', '2023-12-01', '2024-03-01', '2024-06-01', '2024-09-01', '2024-12-01'], dtype='datetime64[ns]', freq='QS-DEC')

这跟你想要的结果差不多。

但是不幸的是:

pd.date_range('2023-01-05', '2024-12-01', freq='2QS-DEC')
# DatetimeIndex(['2023-03-01', '2023-09-01', '2024-03-01', '2024-09-01'], dtype='datetime64[ns]', freq='2QS-DEC')

这个方法会从下一个可用的季度开始,这里就是 '2023-03-01'

再说一次,不幸的是,pandas中没有可以锚定的学期频率。

一个解决办法可能是先获取所有的季度数据,然后筛选出第二和第四季度:

out = pd.date_range('2023-01-05', '2024-12-01', inclusive='left', freq='QS-DEC')
out = out[out.quarter%2 == 0]

输出结果:

DatetimeIndex(['2023-06-01', '2023-12-01', '2024-06-01'], dtype='datetime64[ns]', freq=None)

或者使用 MS(这个方法可能效率更低,因为我们需要丢弃更多不需要的月份):

out = pd.date_range('2023-01-05', '2024-12-01', inclusive='left', freq='MS')
out = out[out.month.isin([1, 6])]

撰写回答