Python 使用每年唯一的日期范围在dataframe中创建一个新列

Python 使用每年唯一的日期范围在dataframe中创建一个新列,python,pandas,date,pandas-groupby,Python,Pandas,Date,Pandas Groupby,我有一个如下形式的数据框: df = pd.DataFrame({'Date':['2017-01-01', '2017-02-13', '2018-03-01', '2018-04-01'], 'Value':[1,2,3,4]}) 每年我都有一个不同的日期范围(例如2017年从2017年2月2日到2017年2月15日,2018年从2018年3月3日到2018年4月4日)作为字典存储 dates_dict = {2017: ('2017-02-02', '2017-02-15'), 2018

我有一个如下形式的数据框:

df = pd.DataFrame({'Date':['2017-01-01', '2017-02-13', '2018-03-01', '2018-04-01'], 'Value':[1,2,3,4]})
每年我都有一个不同的日期范围(例如2017年从2017年2月2日到2017年2月15日,2018年从2018年3月3日到2018年4月4日)作为字典存储

dates_dict = {2017: ('2017-02-02', '2017-02-15'), 2018: ('2018-03-03', '2018-04-04')}
我想在我的数据框中创建一个新列,如果日期在该日期范围内,则为True,否则为False。对于给定的示例,输出为:

df =    Date        Value  in_range
     0  2017-01-01  1      False
     1  2017-02-13  2      True
     2  2018-03-01  3      False
     3  2018-04-01  4      True
我目前的解决办法是:

temp = []
for name, group in df.groupby(df['Date'].dt.year):
    temp.append((group['Date'] >= dates_dict[name][0]) & (group['Date'] <= 
    dates_dict[name][1]))
in_range = pd.concat(temp)
in_range = in_range.rename('in_range')
df = df.merge(in_range.to_frame(), left_index=True, right_index=True)
temp=[]
对于名称,df.groupby中的组(df['Date'].dt.year):
临时追加((组['Date']>=日期[名称][0])和(组['Date']]设置

通过将词典转换为实际包含
pd.date\u范围
,您可以提高解决方案的效率。这两种解决方案都假设您进行了此转换:

dates_dict = {k: pd.date_range(s, e) for k, (s, e) in dates_dict.items()}
选项1
通过字典查找使用
应用

df.Date.apply(lambda x: x in dates_dict[x.year], 1)

0    False
1     True
2    False
3     True
Name: Date, dtype: bool
选项2
使用列表理解的性能稍高的选项:

df['in_range'] = [i in dates_dict[i.year] for i in df.Date]

        Date  Value  in_range
0 2017-01-01      1     False
1 2017-02-13      2      True
2 2018-03-01      3     False
3 2018-04-01      4      True
计时


您可以使用
map
为每个
日期使用字典中的值创建序列
ser
,然后在
之间使用
,例如:

ser = df.Date.dt.year.map(dates_dict)
df['in_range'] = df.Date.between(pd.to_datetime(ser.str[0]), pd.to_datetime(ser.str[1]))
你会得到:

        Date  Value  in_range
0 2017-01-01      1     False
1 2017-02-13      2      True
2 2018-03-01      3     False
3 2018-04-01      4      True

多亏了这一点,我还没有看这方面的性能,但是你认为有矢量化的实现吗?我想知道,如果我有一个开始-结束元组的列表,然后逐步完成,然后做一个矢量化比较,或者将所有创建的系列合并为一个,我想你会得到一个矢量化的解决方案n通过更改跟踪日期范围的方式。我将公布列表理解和应用之间的性能差异,列表理解相当快。
        Date  Value  in_range
0 2017-01-01      1     False
1 2017-02-13      2      True
2 2018-03-01      3     False
3 2018-04-01      4      True