创建没有闰日的datetimeindex

bsxbgnwa  于 2021-09-08  发布在  Java
关注(0)|答案(1)|浏览(303)

我想创建一个pandas datetimeindex,它包含不同年份闰日前后的一系列日期。有些年份是闰年,有些年份不是。但这里需要注意的是,我希望所有这些日期列表的长度相同。让我们看一些例子。

import pandas as pd
from datetime import timedelta

leap=pd.date_range('2020-02-27-12',pd.to_datetime('2020-02-27-12')+dt.timedelta(days=2),freq='6H')

DatetimeIndex(['2020-02-27 12:00:00', '2020-02-27 18:00:00',
               '2020-02-28 00:00:00', '2020-02-28 06:00:00',
               '2020-02-28 12:00:00', '2020-02-28 18:00:00',
               '2020-02-29 00:00:00', '2020-02-29 06:00:00',
               '2020-02-29 12:00:00'],
              dtype='datetime64[ns]', freq='6H')
len(leap)
9

在这种格式中,避免闰日最常见的方法之一就是将其从列表中删除。

leap=leap[(leap.day != 29) | (leap.month != 2)]
len(leap)
6

如果我只想删除闰日,而不关心列表的具体长度,那么这个方法就可以了。
让我们在非闰年做同样的练习。

leap=pd.date_range('2021-02-27-12',pd.to_datetime('2021-02-27-12')+dt.timedelta(days=2),freq='6H')

DatetimeIndex(['2021-02-27 12:00:00', '2021-02-27 18:00:00',
               '2021-02-28 00:00:00', '2021-02-28 06:00:00',
               '2021-02-28 12:00:00', '2021-02-28 18:00:00',
               '2021-03-01 00:00:00', '2021-03-01 06:00:00',
               '2021-03-01 12:00:00'],
              dtype='datetime64[ns]', freq='6H')

len(leap)
9

当然,前两个长度相同。但是,当我们从第一个列表中删除闰日期时,我们现在可以看到长度不同,如6=/9。
这就引出了一个最终的问题:我如何创建一个Pandas日期范围,将第一个列表,跳过闰日,直接进入三月,将列表的长度保持在9?
在上下文中,我使用以日期为中心的方法为地理空间(3d)数据编制索引。例如,如果我想查看1月5日地球上某个点的数据,我会在1月5日(1月3-7日)前后两天分析数据。在长时间(>30年)使用这种方法时,我对所分析的变量有了更好的气候感觉。为了做这个索引,我在日期上循环,并使用上面描述的pandas日期范围方法。这是我用来解决地理空间(3d)数据索引问题的循环:

times=pd.date_range('1979-09-01','1980-04-30-18', freq='6H')
final_times = times[(times.day != 29) | (times.month != 2)]
years=np.arange(1979,2020,1)
for i in final_times:
    print(i)

    times_list=[]

    for j in years:
        times_forward=pd.date_range(i.replace(year=j),i.replace(year=j)+dt.timedelta(days=2), freq='6H')
        times_back=pd.date_range(i.replace(year=j)-dt.timedelta(days=2),i.replace(year=j)-dt.timedelta(hours=6), freq='6H')
        total_times=times_forward.union(times_back)
        times_list.append(total_times)
    combined_times=pd.DatetimeIndex([item for sublist in times_list for item in sublist]).sort_values()

当按原样运行此代码时,围绕闰日的日期列表的长度比不在闰日附近的日期列表的长度短。

hujrc8aj

hujrc8aj1#

如果你只是使用 DateOffset 对象,这个问题在某种程度上是为您处理的:

>>> pd.date_range('2021-02-27-12', periods=9, freq='6H')
DatetimeIndex(['2021-02-27 12:00:00', '2021-02-27 18:00:00',
               '2021-02-28 00:00:00', '2021-02-28 06:00:00',
               '2021-02-28 12:00:00', '2021-02-28 18:00:00',
               '2021-03-01 00:00:00', '2021-03-01 06:00:00',
               '2021-03-01 12:00:00'],
              dtype='datetime64[ns]', freq='6H')
>>> pd.date_range('2021-02-27-12', periods=9, freq='6H') - pd.DateOffset(years=1)
DatetimeIndex(['2020-02-27 12:00:00', '2020-02-27 18:00:00',
               '2020-02-28 00:00:00', '2020-02-28 06:00:00',
               '2020-02-28 12:00:00', '2020-02-28 18:00:00',
               '2020-03-01 00:00:00', '2020-03-01 06:00:00',
               '2020-03-01 12:00:00'],
              dtype='datetime64[ns]', freq=None)

这就是你想要的,只要你参考的年份不是闰年。请注意,如果您以闰年为基础,您将有两个相同的日期,即,您将比较上一年或下一年的28日和29日:

>>> pd.date_range('2020-02-27-12', periods=9, freq='6H')
DatetimeIndex(['2020-02-27 12:00:00', '2020-02-27 18:00:00',
               '2020-02-28 00:00:00', '2020-02-28 06:00:00',
               '2020-02-28 12:00:00', '2020-02-28 18:00:00',
               '2020-02-29 00:00:00', '2020-02-29 06:00:00',
               '2020-02-29 12:00:00'],
              dtype='datetime64[ns]', freq='6H')
>>> pd.date_range('2020-02-27-12', periods=9, freq='6H') + pd.DateOffset(years=1)
DatetimeIndex(['2021-02-27 12:00:00', '2021-02-27 18:00:00',
               '2021-02-28 00:00:00', '2021-02-28 06:00:00',
               '2021-02-28 12:00:00', '2021-02-28 18:00:00',
               '2021-02-28 00:00:00', '2021-02-28 06:00:00',
               '2021-02-28 12:00:00'],
              dtype='datetime64[ns]', freq=None)

我不确定这是否有问题− 然后索引包含重复的项,但我想这是唯一的缺点。
基于此,这里有一个函数,该函数为给定日期提供每年日期(范围内)的索引,以进行比较:

def compare_times(datetime, periods=9, freq='6H', years=np.arange(1979, 2021)):
    ref_index = pd.DatetimeIndex([
        *pd.date_range(datetime, periods=1 + periods // 2, freq=f'-{freq}')[::-1],
        *pd.date_range(datetime, periods=1 + periods // 2, freq=freq)[1:]
    ])
    return pd.DatetimeIndex(np.concatenate([ref_index + pd.DateOffset(years=y -datetime.year) for y in years]))

现在已经没有问题了,只要你不在2月29日调用函数。如果您这样做,非闰年将返回相同数量的项目,但2月28日的条目重复:

>>> compare_times(pd.Timestamp(2020, 2, 29))
DatetimeIndex(['1979-02-28 00:00:00', '1979-02-28 06:00:00',
               '1979-02-28 12:00:00', '1979-02-28 18:00:00',
               '1979-02-28 00:00:00', '1979-02-28 06:00:00',
               '1979-02-28 12:00:00', '1979-02-28 18:00:00',
               '1979-03-01 00:00:00', '1980-02-28 00:00:00',
               ...
               '2019-03-01 00:00:00', '2020-02-28 00:00:00',
               '2020-02-28 06:00:00', '2020-02-28 12:00:00',
               '2020-02-28 18:00:00', '2020-02-29 00:00:00',
               '2020-02-29 06:00:00', '2020-02-29 12:00:00',
               '2020-02-29 18:00:00', '2020-03-01 00:00:00'],
              dtype='datetime64[ns]', length=378, freq=None)

在这里你可以看到1979年的复制品。

相关问题