Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用另一个事件数据帧屏蔽日期数据帧_Python_Pandas - Fatal编程技术网

Python 使用另一个事件数据帧屏蔽日期数据帧

Python 使用另一个事件数据帧屏蔽日期数据帧,python,pandas,Python,Pandas,我有一个如下的数据帧 df = pd.DataFrame({"date": pd.date_range(start="2012-03-01", end="2012-03-05"), "date+1": pd.date_range(start="2012-03-02", end="2012-03-06"),

我有一个如下的数据帧

df = pd.DataFrame({"date": pd.date_range(start="2012-03-01", end="2012-03-05"),
                       "date+1": pd.date_range(start="2012-03-02", end="2012-03-06"),
                       "date+2": pd.date_range(start="2012-03-03", end="2012-03-07")})
我还有另一个数据框,表示具有开始日期和结束日期的事件,如下所示

event = pd.DataFrame({"event": ["A", "B"],
                      "start": ["2012-03-02", "2012-03-04"],
                      "end": ["2012-03-03", "2012-03-06"]})
event["start"] = pd.to_datetime(event["start"])
event["end"] = pd.to_datetime(event["end"])
我想创建一个掩码数据框,如果df中的任何日期介于事件数据框中任何事件的开始日期和结束日期之间,则该掩码数据框将返回True。预期输出应为

0,  1,  1
1,  1,  1
1,  1,  1
1,  1,  1
1,  1,  0
该预期输出对应于df

2012-03-01,  2012-03-02,  2012-03-03
2012-03-02,  2012-03-03,  2012-03-04
2012-03-03,  2012-03-04,  2012-03-05
2012-03-04,  2012-03-05,  2012-03-06
2012-03-05,  2012-03-06,  2012-03-07

如您所见,只有2012-03-01和2012-03-07不在事件数据框中的任何事件之间。循环的计算代价可能很高。您能给我一些建议吗?

您可以使用笛卡尔连接,然后检查日期是否介于间隔的开始和结束之间,并聚合:

# cartesian join
z = (df
    .stack().reset_index().assign(k=1)
    .merge(event.assign(k=1)))

# check if date between start and end
z['mask'] = z[0].between(z['start'], z['end'])

# aggregate
df_m = z.groupby(['level_0', 'level_1'])['mask'].max().unstack().astype(int)
df_m
输出:

level_1  date  date+1  date+2
level_0                      
0           0       1       1
1           1       1       1
2           1       1       1
3           1       1       1
4           1       1       0

另外,如果您使用的是较新版本的
pandas
(1.2.0+),您可以直接使用
merge(how='cross')
,而不是在合并前将
k=1
分配给两个帧,然后检查日期是否在间隔的开始和结束之间,并聚合:

# cartesian join
z = (df
    .stack().reset_index().assign(k=1)
    .merge(event.assign(k=1)))

# check if date between start and end
z['mask'] = z[0].between(z['start'], z['end'])

# aggregate
df_m = z.groupby(['level_0', 'level_1'])['mask'].max().unstack().astype(int)
df_m
输出:

level_1  date  date+1  date+2
level_0                      
0           0       1       1
1           1       1       1
2           1       1       1
3           1       1       1
4           1       1       0
另外,如果您使用的是较新版本的
pandas
(1.2.0+),则可以使用
merge(how='cross')
直接创建一个来自
事件的<

intervals = pd.IntervalIndex.from_tuples([*zip(event.start, event.end)], 
                                         closed = 'both')

IntervalIndex([[2012-03-02, 2012-03-03], [2012-03-04, 2012-03-06]],
              closed='both',
              dtype='interval[datetime64[ns]]')
运行于
df

df.applymap(lambda df: intervals.contains(df).any()).astype(int)
 
   date  date+1  date+2
0     0       1       1
1     1       1       1
2     1       1       1
3     1       1       1
4     1       1       0
事件创建一个

intervals = pd.IntervalIndex.from_tuples([*zip(event.start, event.end)], 
                                         closed = 'both')

IntervalIndex([[2012-03-02, 2012-03-03], [2012-03-04, 2012-03-06]],
              closed='both',
              dtype='interval[datetime64[ns]]')
运行于
df

df.applymap(lambda df: intervals.contains(df).any()).astype(int)
 
   date  date+1  date+2
0     0       1       1
1     1       1       1
2     1       1       1
3     1       1       1
4     1       1       0

使用datetime import timedelta中的
如何?您可以使用诸如
datetime('2012-03-01')+timedelta(days=1)
这只是一个示例。如果你愿意,我会给出完整的代码。我可以看看完整的代码吗?使用datetime import timedelta的
怎么样?您可以使用诸如
datetime('2012-03-01')+timedelta(days=1)
这只是一个示例。如果你愿意,我会给出完整的代码。我可以看看完整的代码吗?