Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.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_Datetime - Fatal编程技术网

Python 如何在重叠的日期时间范围内合并具有列的两个数据帧

Python 如何在重叠的日期时间范围内合并具有列的两个数据帧,python,pandas,datetime,Python,Pandas,Datetime,从这个问题开始。但是我的datetime范围列可能相互重叠 例如: >>>df_1 timestamp A B 0 2019-07-14 05:31:00 0.020228 0.026572 1 2019-07-14 06:32:00 0.057780 0.175499 2 2019-07-14 07:02:00 0.076623 0.875499 >>>df_2

从这个问题开始。但是我的datetime范围列可能相互重叠

例如:

>>>df_1

  timestamp              A           B
0 2019-07-14 05:31:00    0.020228    0.026572
1 2019-07-14 06:32:00    0.057780    0.175499
2 2019-07-14 07:02:00    0.076623    0.875499

>>>df_2

  start                  end                    event
0 2019-07-14 05:30:00    2019-07-14 06:30:00    E1
1 2019-07-14 06:00:00    2019-07-14 07:00:00    E2
2 2019-07-14 06:30:01    2019-07-14 07:30:00    E3
3 2019-07-14 07:30:01    2019-07-14 08:30:00    E4
我想在
df_2
的间隔中找到
df_1
A
。我预期的结果如下:

  start                  end                    event timestamp             A
0 2019-07-14 05:30:00    2019-07-14 06:30:00    E1    2019-07-14 05:31:00    0.020228
1 2019-07-14 06:00:00    2019-07-14 07:00:00    E2    2019-07-14 06:32:00    0.057780
2 2019-07-14 06:30:01    2019-07-14 07:30:00    E3    2019-07-14 06:32:00    0.057780
3 2019-07-14 06:30:01    2019-07-14 07:30:00    E3    2019-07-14 07:02:00    0.076623
我遵循上面链接中的答案,但我没有找到实现目标的方法。当我试图使用得票最高的答案时,出现了以下错误

KeyError:“索引器未与唯一的间隔集相交”

有人能帮我吗?提前感谢。

这与您需要的功能非常相似。下面是我如何调整该解决方案以适应您的问题,但可能会有更好的实现:

bins = list(zip(df2['start'],df2['end']))
def overlapping_bins(x):
    return pd.Series([l for l in bins if l[0] <= x <= l[1]])

df3=pd.concat([df1, df1.timestamp.apply(overlapping_bins).stack().reset_index(1, drop=True)], 
     axis=1).rename(columns={0: 'bins'})

 #Create start and end columns and drop bins
 df3.loc[:, 'start'] = df3.bins.map(lambda x: x[0])
 df3.loc[:, 'end'] = df3.bins.map(lambda x: x[1])
 df3.drop('bins',axis=1,inplace=True)

 #Merge df2 with df3 on the common columns
 df4=df2.merge(df3).drop('B',axis=1)
这与您需要的功能非常相似。下面是我如何调整该解决方案以适应您的问题,但可能会有更好的实现:

bins = list(zip(df2['start'],df2['end']))
def overlapping_bins(x):
    return pd.Series([l for l in bins if l[0] <= x <= l[1]])

df3=pd.concat([df1, df1.timestamp.apply(overlapping_bins).stack().reset_index(1, drop=True)], 
     axis=1).rename(columns={0: 'bins'})

 #Create start and end columns and drop bins
 df3.loc[:, 'start'] = df3.bins.map(lambda x: x[0])
 df3.loc[:, 'end'] = df3.bins.map(lambda x: x[1])
 df3.drop('bins',axis=1,inplace=True)

 #Merge df2 with df3 on the common columns
 df4=df2.merge(df3).drop('B',axis=1)

也可以使用numpy广播和布尔索引来完成,如下所示

array([[ True, False, False],
       [False,  True, False],
       [False,  True,  True],
       [False, False, False]])
##加载样本数据
df1=pd.数据帧([('0','2019-07-14 05:31:00','0.020228','0.026572'),('1','2019-07-14 06:32:00','0.057780','0.175499'),('2','2019-07-14 07:02:00','0.076623','0.875499'),列=('id','timestamp','A','B'))
df2=pd.数据帧([('0','2019-07-14 05:30:00','2019-07-14 06:30:00','E1'),('1','2019-07-14 06:00:00','2019-07-14 06:00','E2'),('2','2019-07-14 06:30:01','2019-07-14 07:30:00','E3'),('3','2019-07-07-14 07-14 07:30:00','E4'),列='id','start','end事件'))
df1[“时间戳”]=pd.to_datetime(df1[“时间戳”])
df2[“开始”]=pd.to_日期时间(df2[“开始”])
df2[“结束”]=pd.to_日期时间(df2[“结束”])
解决方案

##df2[[“开始”]]是大小为m的列向量,df1.timestamp.values是行
##大小为n的向量,然后宽浇铸将得到形状为m的矩阵,即
##比较每对m和n的结果
比较=(df2[[“开始”].valuesdf1.timestamp.values)
##获取从0到满足条件的矩阵大小范围内的单元格编号
ind=np.arange(len(df1)*len(df2))[compare.ravel()]
##根据单元格编号计算行和列索引
pd.concat([df2.iloc[ind//len(df1)]。重置索引(drop=True),df1.iloc[ind%len(df1)]。重置索引(drop=True)],轴=1,排序=False)
结果

    start               end                event    timestamp             A  B
0   2019-07-14 05:30:00 2019-07-14 06:30:00 E1  2019-07-14 05:31:00 0.020228    0.026572
1   2019-07-14 06:00:00 2019-07-14 07:00:00 E2  2019-07-14 06:32:00 0.057780    0.175499
2   2019-07-14 06:30:01 2019-07-14 07:30:00 E3  2019-07-14 06:32:00 0.057780    0.175499
3   2019-07-14 06:30:01 2019-07-14 07:30:00 E3  2019-07-14 07:02:00 0.076623    0.875499

编辑
对于@baccandr的评论,这里有一些关于索引如何工作的更多解释

在比较之后,我们得到具有如下布尔值的比较矩阵

array([[ True, False, False],
       [False,  True, False],
       [False,  True,  True],
       [False, False, False]])
  • 您可以将此矩阵视为表,其中列表示索引为
    df1
    ,即(0,1,2),行表示索引为
    df2
    ,即(0,1,2,3)
  • 如果df1和df2中的对应行满足条件,例如df1的第0行和df2的第0行,则单元格中的值为真;df1的第2行和df2的第1行满足条件
  • 为了分别从df1和df2中找到满足条件的行,我们可以直接使用
    compare
    作为索引,就像df1[compare.T]和df2[compare]一样,但它不会给出正确的行配对顺序。这将以索引的递增顺序给出这两个行,但这并不总是正确的
  • 现在我们的目标是以正确的顺序获得满足条件的两个数据帧的索引。所以我们需要的是df1的索引[0,1,2,2]和df2的索引[0,1,1,2]。使用df1和df2中的这些索引,我们可以从两者中以正确的顺序获得匹配
  • 所以我们在这里做的是从左到右,然后再从左到右,再从左到右,给每个细胞一个唯一的数字。然后过滤条件满足的单元格,并将其转换为df1和df2的索引
由于矩阵表示矩阵格式的2个数据帧的索引,我认为np.where可能不起作用。另一种方法是使用
compare
作为df2的索引,只查找df1的索引,如下所示

array([[ True, False, False],
       [False,  True, False],
       [False,  True,  True],
       [False, False, False]])
这将为df2的每一行重复df1的索引,并按df2的顺序查找df1的索引

ind_df1=np.tile(np.arange(len(df1)),len(df2))[compare.ravel()]
pd.concat([df2[compare].reset_index(drop=True),df1.iloc[ind_df1].reset_index(drop=True)],axis=1,sort=False)

我希望这能说明问题,如果您有其他想法,那么我希望在评论或答案中看到它

也可以使用numpy广播和布尔索引来完成,如下所示

array([[ True, False, False],
       [False,  True, False],
       [False,  True,  True],
       [False, False, False]])
##加载样本数据
df1=pd.数据帧([('0','2019-07-14 05:31:00','0.020228','0.026572'),('1','2019-07-14 06:32:00','0.057780','0.175499'),('2','2019-07-14 07:02:00','0.076623','0.875499'),列=('id','timestamp','A','B'))
df2=pd.数据帧([('0','2019-07-14 05:30:00','2019-07-14 06:30:00','E1'),('1','2019-07-14 06:00:00','2019-07-14 06:00','E2'),('2','2019-07-14 06:30:01','2019-07-14 07:30:00','E3'),('3','2019-07-07-14 07-14 07:30:00','E4'),列='id','start','end事件'))
df1[“时间戳”]=pd.to_datetime(df1[“时间戳”])
df2[“开始”]=pd.to_日期时间(df2[“开始”])
df2[“结束”]=pd.to_日期时间(df2[“结束”])
解决方案

##df2[[“开始”]]是大小为m的列向量,df1.timestamp.values是行
##大小为n的向量,然后宽浇铸将得到形状为m的矩阵,即
##比较每对m和n的结果
比较=(df2[[“开始”].valuesdf1.timestamp.values)
##获取从0到满足条件的矩阵大小范围内的单元格编号
ind=np.arange(len(df1)*len(df2))[compare.ravel()]
##根据单元格编号计算行和列索引
pd.concat([df2.iloc[ind//len(df1)]。重置索引(drop=True),df1.iloc[ind%len(df1)]。重置索引(drop=True)],轴=1,排序=False)
结果

    start               end                event    timestamp             A  B
0   2019-07-14 05:30:00 2019-07-14 06:30:00 E1  2019-07-14 05:31:00 0.020228    0.026572
1   2019-07-14 06:00:00 2019-07-14 07:00:00 E2  2019-07-14 06:32:00 0.057780    0.175499
2   2019-07-14 06:30:01 2019-07-14 07:30:00 E3  2019-07-14 06:32:00 0.057780    0.175499
3   2019-07-14 06:30:01 2019-07-14 07:30:00 E3  2019-07-14 07:02:00 0.076623    0.875499

编辑
对于@baccandr的评论,这里有一些关于索引如何工作的更多解释

在比较之后,我们得到具有如下布尔值的比较矩阵

array([[ True, False, False],
       [False,  True, False],
       [False,  True,  True],
       [False, False, False]])
  • 你可以想到