Python 日期与另一个表的开始日期和结束日期的左联接
前两个表下面是Python 日期与另一个表的开始日期和结束日期的左联接,python,python-3.x,pandas,Python,Python 3.x,Pandas,前两个表下面是cat1和cat2表 基本上,我希望用cat2加入cat1,其中cat1日期介于cat2的开始/结束日期之间。 最后一个表是结果,我应该如何有效地实现这一点?注意,我在实表中有100k条记录。 顺便说一句,如果cat1的日期在两个StartDate和EndDate中(两行cat2),那么它将在输出表中有两行 请在下面查找cat1和cat2 将熊猫作为pd导入 起始日期时间导入日期 cat1=pd.DataFrame({ “CatID”:[1,2,3], “日期”:[日期(2019
cat1
和cat2
表
基本上,我希望用cat2
加入cat1
,其中cat1
日期介于cat2
的开始/结束日期之间。
最后一个表是结果,我应该如何有效地实现这一点?注意,我在实表中有100k条记录。
顺便说一句,如果cat1
的日期在两个StartDate和EndDate中(两行cat2
),那么它将在输出表中有两行
请在下面查找cat1
和cat2
将熊猫作为pd导入
起始日期时间导入日期
cat1=pd.DataFrame({
“CatID”:[1,2,3],
“日期”:[日期(2019,10,1)、日期(2019,11,1)、日期(2019,12,1)]
})
cat2=pd.DataFrame({
“有趣”:[1,2,3,4],
“起始日期”:[日期(2019,10,1)、日期(2019,11,1)、日期(2019,11,1)、日期(2018,10,6)],
“截止日期”:[日期(2019,10,30)、日期(2019,11,30)、日期(2019,11,30)、日期(2018,10,6)]
})
我已经在这里尝试了解决方案
#df2[[“start”]]是大小为m的列向量,df1.timestamp.values是行
##大小为n的向量,然后宽浇铸将得到形状为m的矩阵,即
##比较每对m和n的结果
比较=(cat2[[“StartDate”].values=cat1.Date.values)
##获取从0到满足条件的矩阵大小范围内的单元格编号
ind=np.arange(len(cat1)*len(cat2))[compare.ravel()]
##根据单元格编号计算行和列索引
pd.concat([cat2.iloc[ind//len(cat1)]。重置索引(下降=真),cat1.iloc[ind%len(cat1)]。重置索引(下降=真),轴=1,排序=假)
我得到了
这不是我想要的,因为它缺少最后一行(因为我需要的是左连接)。您可以使用交叉连接和
系列。between()
:
您可以使用交叉联接和
系列之间的连接()
你产生的是一个“内在”连接。在连接右列之前,将其作为单独的数据框进行构建。确保行数相等
# df2[["start"]] is a column vector of size m and df1.timestamp.values is row
## vector of size n then broad cast will result matrix of shape m,n which is
## result of comparing each pair of m and n
compare = (cat2[["StartDate"]].values<=cat1.Date.values) & (cat2[["EndDate"]].values>=cat1.Date.values)
## get cell numbers which is in range 0 to matrix size which meets the condition
ind_old = np.arange(len(cat1)*len(cat2))[compare.ravel()]
ind_new = np.arange(len(cat1)*len(cat2))[compare.T.ravel()]
cat1_new = pd.DataFrame(np.nan, index=list(cat2.index), columns=cat1.columns)
## match the rows of cat1 to those of cat2
cat1_new.iloc[ind_new%len(cat2)] = cat1.iloc[ind_old%len(cat1)].reset_index(drop=True)
## calculate row and column index from cell number
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
## concat
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
# Interesting StartDate EndDate CatID Date
# 0 1 2019-10-01 2019-10-30 1.0 2019-10-01
# 1 2 2019-11-01 2019-11-30 2.0 2019-11-01
# 2 3 2019-11-01 2019-11-30 2.0 2019-11-01
# 3 4 2018-10-06 2018-10-06 NaN NaN
#df2[[“start”]]是大小为m的列向量,df1.timestamp.values是行
##大小为n的向量,然后宽浇铸将得到形状为m的矩阵,即
##比较每对m和n的结果
比较=(cat2[[“StartDate”].values=cat1.Date.values)
##获取从0到满足条件的矩阵大小范围内的单元格编号
ind_old=np.arange(len(cat1)*len(cat2))[compare.ravel()]
ind_new=np.arange(len(cat1)*len(cat2))[compare.T.ravel()]
cat1_new=pd.DataFrame(np.nan,index=list(cat2.index),columns=cat1.columns)
##将cat1的行与cat2的行匹配
cat1_new.iloc[ind_new%len(cat2)]=cat1.iloc[ind_old%len(cat1)]。重置索引(drop=True)
##根据单元格编号计算行和列索引
打印(pd.concat([cat2,cat1_new],轴=1,排序=False))
##海螺
打印(pd.concat([cat2,cat1_new],轴=1,排序=False))
#有趣的开始日期结束日期CatID日期
# 0 1 2019-10-01 2019-10-30 1.0 2019-10-01
# 1 2 2019-11-01 2019-11-30 2.0 2019-11-01
# 2 3 2019-11-01 2019-11-30 2.0 2019-11-01
#3.4 2018-10-06 2018-10-06楠楠楠
您生成的是一个“内部”联接。在连接右列之前,将其作为单独的数据框进行构建。确保行数相等
# df2[["start"]] is a column vector of size m and df1.timestamp.values is row
## vector of size n then broad cast will result matrix of shape m,n which is
## result of comparing each pair of m and n
compare = (cat2[["StartDate"]].values<=cat1.Date.values) & (cat2[["EndDate"]].values>=cat1.Date.values)
## get cell numbers which is in range 0 to matrix size which meets the condition
ind_old = np.arange(len(cat1)*len(cat2))[compare.ravel()]
ind_new = np.arange(len(cat1)*len(cat2))[compare.T.ravel()]
cat1_new = pd.DataFrame(np.nan, index=list(cat2.index), columns=cat1.columns)
## match the rows of cat1 to those of cat2
cat1_new.iloc[ind_new%len(cat2)] = cat1.iloc[ind_old%len(cat1)].reset_index(drop=True)
## calculate row and column index from cell number
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
## concat
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
# Interesting StartDate EndDate CatID Date
# 0 1 2019-10-01 2019-10-30 1.0 2019-10-01
# 1 2 2019-11-01 2019-11-30 2.0 2019-11-01
# 2 3 2019-11-01 2019-11-30 2.0 2019-11-01
# 3 4 2018-10-06 2018-10-06 NaN NaN
#df2[[“start”]]是大小为m的列向量,df1.timestamp.values是行
##大小为n的向量,然后宽浇铸将得到形状为m的矩阵,即
##比较每对m和n的结果
比较=(cat2[[“StartDate”].values=cat1.Date.values)
##获取从0到满足条件的矩阵大小范围内的单元格编号
ind_old=np.arange(len(cat1)*len(cat2))[compare.ravel()]
ind_new=np.arange(len(cat1)*len(cat2))[compare.T.ravel()]
cat1_new=pd.DataFrame(np.nan,index=list(cat2.index),columns=cat1.columns)
##将cat1的行与cat2的行匹配
cat1_new.iloc[ind_new%len(cat2)]=cat1.iloc[ind_old%len(cat1)]。重置索引(drop=True)
##根据单元格编号计算行和列索引
打印(pd.concat([cat2,cat1_new],轴=1,排序=False))
##海螺
打印(pd.concat([cat2,cat1_new],轴=1,排序=False))
#有趣的开始日期结束日期CatID日期
# 0 1 2019-10-01 2019-10-30 1.0 2019-10-01
# 1 2 2019-11-01 2019-11-30 2.0 2019-11-01
# 2 3 2019-11-01 2019-11-30 2.0 2019-11-01
#3.4 2018-10-06 2018-10-06楠楠楠
谢谢,我用cat2中与cat1匹配的两行尝试了您的解决方案,但出现了错误,请在问题中查找上面的代码。@william007是的,因为重复的日期范围,您在这里的预期输出是什么(因为您有两个相同的日期范围,但编号不同)?谢谢你,你也能更新这个问题吗?我已经用所需的输出更新了这些问题。@william007我已经更新了我的答案。虽然可能有点慢,但你能测试一下吗?谢谢谢谢谢谢,我用cat2中与cat1匹配的两行尝试了您的解决方案,但它抛出了错误,请在问题中查找上面的代码。@william007是的,因为重复的日期范围,您在这里的预期输出是什么(因为您有两个相同的日期范围,但编号不同)?谢谢你,你也能更新这个问题吗?我已经用所需的输出更新了这些问题。@william007我已经更新了我的答案。虽然可能有点慢,但你能测试一下吗?非常感谢。
m=cat1.assign(k=1).merge(cat2.assign(k=1)).drop('k',1)
final=(m[m.Date.between(m.StartDate,m.EndDate)]
.merge(cat1,on=['Date','CatID'],how='right').drop(['StartDate','EndDate'],1))
CatID Date Interesting
0 1 2019-10-01 1.0
1 2 2019-11-01 2.0
2 2 2019-11-01 3.0
3 3 2019-12-01 NaN
# df2[["start"]] is a column vector of size m and df1.timestamp.values is row
## vector of size n then broad cast will result matrix of shape m,n which is
## result of comparing each pair of m and n
compare = (cat2[["StartDate"]].values<=cat1.Date.values) & (cat2[["EndDate"]].values>=cat1.Date.values)
## get cell numbers which is in range 0 to matrix size which meets the condition
ind_old = np.arange(len(cat1)*len(cat2))[compare.ravel()]
ind_new = np.arange(len(cat1)*len(cat2))[compare.T.ravel()]
cat1_new = pd.DataFrame(np.nan, index=list(cat2.index), columns=cat1.columns)
## match the rows of cat1 to those of cat2
cat1_new.iloc[ind_new%len(cat2)] = cat1.iloc[ind_old%len(cat1)].reset_index(drop=True)
## calculate row and column index from cell number
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
## concat
print(pd.concat([cat2, cat1_new], axis=1, sort=False))
# Interesting StartDate EndDate CatID Date
# 0 1 2019-10-01 2019-10-30 1.0 2019-10-01
# 1 2 2019-11-01 2019-11-30 2.0 2019-11-01
# 2 3 2019-11-01 2019-11-30 2.0 2019-11-01
# 3 4 2018-10-06 2018-10-06 NaN NaN