Pandas多列容差合并数据框

3

我有两个数据框,我想使用两列作为关键字将它们合并,并创建另一个合并的数据框。 其中,Column1是字符串类型,Column2是浮点型。 我想在Column2上设置0.01的公差,使得来自Dataframe1的(John, 1.12)和来自Dataframe2的(John, 1.13)可以在同一行中出现。 我该如何实现?

例如: 两个数据框:

df1 = pd.DataFrame({"Name":["John","Millon"], "MarketVal":[1.12,2.11], "Left_Product":["Sugar","Salt"]})
df2 = pd.DataFrame({"Name":["John","Rex"], "MarketVal":[1.13,3.11], "right_Product":["Sugar","Salt"]})

如果我执行:

dfMerge = pd.merge(df1,df2,on=["Name","MarketVal"], how= "outer")

如果MarketVal在两个数据框中不同,那么这将为“John”创建2行。但我想保持容差为0.01,使它们位于同一行。

    Actual :->
     Name  MarketVal Left_Product right_Product
0    John       1.12        Sugar           NaN
1  Millon       2.11         Salt           NaN
2    John       1.13          NaN         Sugar
3     Rex       3.11          NaN          Salt

Expected :->

     Name  MarketVal Left_Product right_Product
0    John       1.12        Sugar           Sugar
1  Millon       2.11         Salt           NaN
2     Rex       3.11          NaN          Salt

如果存在多个左侧或右侧产品的名称在容差范围内相同,如MarketVal,会发生什么情况呢?例如,在df2中存在另一个名为John 1.13的产品。 - ALollz
请查看merge-asof - sushanth
1
如果在公差范围内存在多行,则应创建另一行。即,如果df2中的3行在df1的公差范围内,则应为每个组合创建3行。 - Milan
另外,merge-asof 在多列上无法正常工作。 - Milan
1个回答

1
仅在“Name”上合并,然后使用掩码仅保留符合所需公差的行。由于外连接,如果任何“MarketVal”为空,则还会保留一行。如果来自外部合并的右侧DataFrame,则还需要更新“MarketVal”。请注意保留HTML标签。
tol = 0.01
m = df1.merge(df2, on='Name', how='outer', suffixes=['', '_r'])
m = m[(m['MarketVal'] - m['MarketVal_r']).abs().le(tol)
      | m[['MarketVal', 'MarketVal_r']].isnull().any(1)]

#     Name  MarketVal Left_Product  MarketVal_r right_Product
#0    John       1.12        Sugar         1.13         Sugar
#1  Millon       2.11         Salt          NaN           NaN
#2     Rex        NaN          NaN         3.11          Sal

m['MarketVal'] = m['MarketVal'].fillna(m['MarketVal_r'])
m = m.drop(columns='MarketVal_r')

#     Name  MarketVal Left_Product right_Product
#0    John       1.12        Sugar         Sugar
#1  Millon       2.11         Salt           NaN
#2     Rex       3.11          NaN          Salt

在多个行与df2匹配的情况下,这将保留所有组合。这里我为John添加了另一行,并将其与df1中的第一行匹配,以及一行不应与任何内容匹配。
df1 = pd.DataFrame({'Name': ['John', 'Millon'], 
                    'MarketVal': [1.12, 2.11], 'Left_Product':['Sugar', 'Salt']})
df2 = pd.DataFrame({'Name': ['John', 'Rex', 'John', 'John'], 
                    'MarketVal': [1.13, 3.11, 1.125, 17], 
                    'right_Product': ['Sugar', 'Salt', 'coffee', 'bad_item']})

#... the above code
print(m)

     Name  MarketVal Left_Product right_Product
0    John       1.12        Sugar         Sugar
1    John       1.12        Sugar        Coffee
3  Millon       2.11         Salt           NaN
4     Rex       3.11          NaN          Salt

1
谢谢你的帮助。我将使用真实数据进行检查,并进行更新。 - Milan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接