问题描述
我试图找出一组日期范围与较大日期范围不重叠的差距。在下面的示例中,我想找到 daterange_1
到 daterange_3
不重叠 big_daterange
的每个间隙。
目前我已经走到这一步,但我仍然坚持从 diff
中提取差距,如果这是最好的方法的话。
import pandas as pd
daterange_1 = pd.date_range("2009-01-01","2010-01-01")
daterange_2 = pd.date_range("2012-01-01","2014-01-01")
daterange_3 = pd.date_range("2016-01-01","2019-01-01")
big_daterange = pd.date_range("2001-01-01","2021-01-01")
combined = daterange_1.union(daterange_2).union(daterange_3)
# Get the dates in big_daterange that aren't in combined
diff = big_daterange.difference(combined)
我最感兴趣的是如何提取间隙(其中间隙是连续日期时间的日期范围)并像这样创建它们的列表:
gaps = [gap_daterange_1,gap_daterange_2,...]
解决方法
试试:
s = diff.to_series()
grp = s.diff().ne(pd.Timedelta(days=1)).cumsum()
gaps = s.groupby(grp).agg(['min','max'])
gaps
输出:
min max
1 2001-01-01 2008-12-31
2 2010-01-02 2011-12-31
3 2014-01-02 2015-12-31
4 2019-01-02 2021-01-01
详情:
首先,使用 to_series
将 DateTimeIndex 转换为 pd.Series。
接下来使用 diff
找出两个连续值之间的差异。
如果 diff 大于一天,则将此记录标记为 True。使用 cumsum
在 True 记录之间创建记录组。最后,groupby
使用 max 和 min 来查找每个组的开始和结束。
您可以使用 reindex
方法。
到处都能找到 NaT,这是因为 dtiX 中缺少日期:
dti1 = pd.date_range("2009-01-01","2010-01-01")
dti2 = pd.date_range("2012-01-01","2014-01-01")
dti3 = pd.date_range("2016-01-01","2019-01-01")
dti = pd.date_range("2001-01-01","2021-01-01")
sr = pd.concat([dti1.to_series(),dti2.to_series(),dti3.to_series()]) \
.sort_index().reindex(dti)
sr = sr[sr.isnull()]
>>> sr.index
DatetimeIndex(['2001-01-01','2001-01-02','2001-01-03','2001-01-04','2001-01-05','2001-01-06','2001-01-07','2001-01-08','2001-01-09','2001-01-10',...
'2020-12-23','2020-12-24','2020-12-25','2020-12-26','2020-12-27','2020-12-28','2020-12-29','2020-12-30','2020-12-31','2021-01-01'],dtype='datetime64[ns]',length=5111,freq=None)
通过创建不连续天的组来查找差距:
sr = sr.index.to_series()
groups = sr.sub(sr.shift()) \
.fillna(pd.Timedelta(days=1)) \
.ne(pd.Timedelta(days=1)) \
.cumsum()
gaps = sr.groupby(groups).agg(['min','max'])
>>> gaps
min max
0 2001-01-01 2008-12-31
1 2010-01-02 2011-12-31
2 2014-01-02 2015-12-31
3 2019-01-02 2021-01-01