Python 熊猫中的复杂条件连接
我想根据复杂的条件连接/合并两个数据帧(具有不同的记录)。条件类似于:Python 熊猫中的复杂条件连接,python,pandas,dataframe,join,merge,Python,Pandas,Dataframe,Join,Merge,我想根据复杂的条件连接/合并两个数据帧(具有不同的记录)。条件类似于: merge rows where df1_row['termination_date'] - df2_row['creation_date'] < pd.Timedelta(n) and df1_row['termination_date'] - df2_row['creation_date'] > pd.Timedelta(-k) and df1_row['smth1'] == df2_row['smth1']
merge rows where
df1_row['termination_date'] - df2_row['creation_date'] < pd.Timedelta(n)
and df1_row['termination_date'] - df2_row['creation_date'] > pd.Timedelta(-k)
and df1_row['smth1'] == df2_row['smth1']
and df1_row['smth2'] != df2_row['smth2']
...
合并行,其中
df1_行['termination_date']-df2_行['creation_date']pd.Timedelta(-k)
和df1_行['smth1']==df2_行['smth1']
和df1_行['smth2']!=df2_行['smth2']
...
在PostgresSQL中,可以非常简单地编写:
df1 join df2
on age(df1.creation_date, df2.termination_date) < interval '...'
and age(df1.creation_date, df2.termination_date) > interval '...'
and df1.smth1 = df2.smth1
...
df1连接df2
在年龄(df1.创建日期,df2.终止日期)<间隔'…'
和年龄(df1.创建日期,df2.终止日期)>间隔“…”
和df1.smth1=df2.smth1
...
但熊猫中不允许这种条件连接。使用python和pandas实现这种逻辑有什么最佳实践/最佳方法吗?确实不是很直截了当。我将逐行检查dataframe 1,并在dataframe 2中找到合适的匹配项(基于标准)。如果有多个候选者,您必须决定如何选择最好的一个(可能只是第一个匹配),然后将匹配与原始行合并
随机导入
进口大熊猫
导入日期时间
#生成一些测试数据帧
df_1=pandas.DataFrame([{
“终止日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“创建日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“smth1”:random.randint(0,1),
“smth2”:random.randint(0,1),
}适用于uu范围内(1000)])
df_2=pandas.DataFrame([{
“终止日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“创建日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“smth1”:random.randint(0,1),
“smth2”:random.randint(0,1),
}适用于uu范围内(1000)])
def try_to_join(行:pandas.Series,其他:pandas.DataFrame,后缀:str=“_right”)->pandas.Series:
“”“尝试基于复杂条件加入。
Args:
行(pandas.Series):要加入的行(左)
其他(pandas.DataFrame):要加入的数据帧(右)
后缀(str,可选):将放在“其他”列上的后缀。默认为“\u right”。
返回:
熊猫系列:加入的系列
"""
#定义条件
条件1=行[“终止日期”]-其他[“创建日期”]pandas.Timedelta(-24,unit=“H”)
条件_3=行[“smth1”]==其他[“smth1”]
条件4=行[“smth2”]!=其他[“smth2”]
#在“其他”中找到满足条件的行
matches=other.loc[条件1和条件2和条件3和条件4,:]
#如果未找到匹配项,则返回原始行
如果匹配。形状[0]==0:
返回行
#TODO:决定如何处理多个匹配(现在选择第一个匹配)
match=matches.iloc[0]
#在“其他”列中添加后缀
match.index=[f“{col}{suffix}”表示match.index中的列]
#将匹配项中的字段添加到原始行
对于match.index中的列:
行[col]=匹配[col]
#返回新行
返回行
#使用上面的函数将2个数据帧连接到一个新的数据帧中
df_join=df_1.应用(lambda行:try_to_join(行,其他=df_2),轴=1)
输出:
creation\u date creation\u date\u right smth1 smth1\u right smth2\
0 2020-11-24 02:10:35 2020-11-24 07:08:40 1 1.0 0
112020-11-2123:46:28 NaT 0南1
2 2020-11-22 21:54:58 2020-11-22 13:27:57 0 0.0 0
3 2020-11-23 18:45:59 2020-11-20 22:58:10 1 1.0 0
4 2020-11-20 13:24:18 2020-11-23 06:18:23 1 1.0 0
.. ... ... ... ... ...
995 2020-11-25 10:40:19 2020-11-24 07:08:40 1 1.0 0
996 2020-11-24 19:27:47 2020-11-24 23:21:32 0 0.0 0
997 2020-11-23 10:18:30 2020-11-24 07:08:40 1 1.0 0
998 2020-11-20 15:54:53 2020-11-24 23:21:32 0 0.0 0
999 2020-11-22 14:19:45 2020-11-24 23:21:32 0 0.0 0
smth2 \u权利终止\u日期终止\u日期\u权利
0 1.0 2020-11-25 01:59:37 2020-11-22 03:38:51
1 NaN 2020-11-23 22:55:26 NaT
2 1.0 2020-11-22 12:47:03 2020-11-24 12:32:50
3 1.0 2020-11-21 18:49:48 2020-11-22 16:16:23
4 1.0 2020-11-22 12:10:14 2020-11-24 00:58:23
.. ... ... ...
995 1.0 2020-11-23 08:04:51 2020-11-22 03:38:51
996 1.0 2020-11-24 09:48:11 2020-11-23 13:43:11
997 1.0 2020-11-24 06:45:34 2020-11-22 03:38:51
998 1.0 2020-11-25 02:19:43 2020-11-23 13:43:11
999 1.0 2020-11-25 09:41:06 2020-11-23 13:43:11
[1000行x 8列]
您会注意到,当没有找到匹配项时,
\u right
的字段将为空。确实不是很直接。我将逐行检查dataframe 1,并在dataframe 2中找到合适的匹配项(基于标准)。如果有多个候选者,您必须决定如何选择最好的一个(可能只是第一个匹配),然后将匹配与原始行合并
随机导入
进口大熊猫
导入日期时间
#生成一些测试数据帧
df_1=pandas.DataFrame([{
“终止日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“创建日期”:datetime.datetime.fromtimestamp(random.randint(16058659191911606297560)),
“smth1”:random.randint(0,1),
“smth2”:random.randint(0,1),
}适用于uu范围内(1000)])
df_2=pandas.DataFrame([{
“终止日期”:datetime.datetime.fromtimestamp(random.randint(1605865919,16