merge_asof pandas python (multiple rows)



我有两个pandas数据框架。这些行需要由两个值(X,Y)坐标匹配,它们不是精确匹配,但在一个公差范围内。我需要将df2中的'VAL'项添加到df1中的'VAL'项,其中(X,Y)匹配。

我试过使用merge_asof,但运气不好。我想如果我能得到merge_asof工作的方式,我期待我可以做加法和重新分配到df2,但到目前为止,我无法得到匹配的工作。

下面是我尝试过的代码示例。

d1 = [ ['wp1',0.0,0.0,10],['wp2',10.0,10.0,5],['wp3',7.0,7.0,5]]
d2 = [ ['wp4',0.1,0.1,5],['wp5',10.2,10.2,8]]
headers = ['Name','X','Y','VAL']
df1 = pd.DataFrame(d1,columns = headers)
df2 = pd.DataFrame(d2,columns = headers)

#attempt at solution just to find matching values
df3 = pd.merge_asof(df1.sort_values('VAL'), df2.sort_values('VAL'),on=['VAL'],by=['X','Y'],direction='nearest',tolerance=1)

#desired solution is to sum 'VAL' from df2 into df1 
d1_final = [ ['wp1',0.0,0.0,10+5],['wp2',10.0,10.0,5+8]]
df1_final = pd.DataFrame(d1_final,columns = headers)

如前所述,您在X,Y上的匹配要求在公差范围内。对于merge_asof(),公差匹配发生在on=参数上。(by=参数提供在on=容忍匹配之前发生的精确匹配——想想grouby)。但是on=只能在单个键上容忍匹配。所以你不能用on=['X','Y']把你带到你想去的地方。merge_asof不能在多个键上进行公差匹配。

快速思考。真希望我现在有更多的时间。只是X上的公差匹配。dropna()。然后对Y值进行二次容差过滤。这些信息会成为合并的一部分。如果Y小于公差-那么只需添加VALs作为最终答案。

df4 = pd.merge_asof(df1.sort_values(['X','Y']), df2.sort_values(['X','Y']), on='X', direction='nearest', tolerance=1)  
df4
Name_x     X   Y_x  VAL_x Name_y   Y_y  VAL_y
0    wp1   0.0   0.0     10    wp4   0.1    5.0
1    wp3   7.0   7.0      5    NaN   NaN    NaN
2    wp2  10.0  10.0      5    wp5  10.2    8.0

然后执行上面列出的过程:

df5 = df4.assign(VAL=np.where((df4['Y_x']-df4['Y_y']).abs()<1, df4['VAL_x']+df4['VAL_y'], np.nan) ) 
.rename(columns={'Name_x':'Name','Y_x':'Y'}).dropna()[['Name','X','Y','VAL']] 
df5
Name     X     Y   VAL
0  wp1   0.0   0.0  15.0
2  wp2  10.0  10.0  13.0

jch解决方案可以使用更新df1所需的name和val设置一个新的df。

如下

import pandas as pd
import numpy as np
d1 = [ ['wp1',0.0,0.0,10],['wp2',10.0,10.0,5],['wp3',7.0,7.0,5]]
d2 = [ ['wp4',0.1,0.1,5],['wp5',10.2,10.2,8]]
headers = ['Name','X','Y','VAL']
df1 = pd.DataFrame(d1,columns = headers)
df2 = pd.DataFrame(d2,columns = headers)
df4 = pd.merge_asof(df1.sort_values(['X','Y']), df2.sort_values(['X','Y']), on='X', direction='nearest', tolerance=1)
print(df4.head())
df5 = df4.assign(VAL=np.where((df4['Y_x']-df4['Y_y']).abs()<1, df4['VAL_x']+df4['VAL_y'], np.nan)).rename(columns={'Name_x':'Name','Y_x':'Y'}).dropna()[['Name','X','Y','VAL']] 
print(df5.head())
print('df1')
print(df1.head())

现在我正在尝试(不成功)更新原始df1并保留原始值,那里没有匹配。

d = df5.set_index('Name')['VAL'].to_dict()
v = df5.filter(like='VAL')
df1[v.columns] = v.replace(d)
print(df1.head())
我现在知道这个映射方案不是一个好方法,下面的值不能正确对应原来的df。
Name     X     Y   VAL
0  wp1   0.0   0.0  15.0
1  wp2  10.0  10.0   NaN
2  wp3   7.0   7.0  13.0

我希望df1像这样更新,但不是NaN为wp2,它应该只是显示df1中wp2的原始VAL。

df5 = df5.set_index(['Name'])
df1 = df1.set_index(['Name'])
df1.update(df5)
print('df1')
print(df1.head())

^工作很好,只要我可以使用'Name'作为索引。

最新更新