Pandas Dataframe Merge Where 1 Column Matches,但另一列的值不存在
Pandas Dataframe Merge Where 1 Column Matches, but Another Column's Values are not Present
这几天我一直在尝试使用 Pandas 来解决问题,但我觉得我遗漏了什么。我有 2 个数据框:
data = {'GMC1':[1, 1, 1, 2, 3, 3, 3],
'Provider1':[100, 101, 102, np.NaN, 104, 105, 106]}
dataframe1 = pd.DataFrame(data)
dataframe1
输出:
GMC1 Provider 1
1 100
1 101
1 102
2 NaN
3 104
3 105
3 106
和
data2 = {'GMC2':[1, 2, 3, 3, 3],
'Provider2':[101, 100, 104, 105, 107]}
dataframe2 = pd.DataFrame(data2)
dataframe2
输出:
GMC2 Provider2
1 101
2 100
3 105
3 104
3 107
我想要返回一个数据帧,它加入 GMC1 = GMC2,并返回 Provider1 中不存在的 Provider2 行,GMC1 和 GMC2 的值相同。
预期输出:
GMC1 GMC2 Provider 2
2 2 100
3 3 107
我尝试过各种使用连接的方法,例如:
(dataframe1.merge(dataframe2, left_on='GMC1', right_on='GMC2',
how='right')
.query('Provider1 != Provider2')
)
但他们并没有完全带回我想要的东西。我知道这有点罗嗦,所以我很乐意详细说明。
非常感谢您的帮助!
一种方法是在两个数据帧上创建一个辅助列,我们称之为 ['GP']
:
dataframe2['Provider2'] = dataframe2['Provider2'].astype(float) # setting this to float so the merge will work
dataframe1['GP'] = dataframe1[['GMC1', 'Provider1']].astype(str).agg(' '.join, axis=1)
dataframe2['GP'] = dataframe2[['GMC2', 'Provider2']].astype(str).agg(' '.join, axis=1)
然后,如果我们在此列上合并并排除 NA:
dataframe1.merge(dataframe2, on='GP', how='outer').query('GMC1.isna()')
会 return:
GMC1 Provider1 GP GMC2 Provider2
7 NaN NaN 2 100.0 2.0 100.0
8 NaN NaN 3 107.0 3.0 107.0
从这里开始,您可以通过一些争论轻松获得所需的解决方案,运行 例如:
result = dataframe1.merge(dataframe2, on='GP', how='outer').query('GMC1.isna()')
result['GMC1'] = result['GP'].apply(lambda x: x.split(' ')[0])
result = result.drop(columns=['GP', 'Provider1'])
将生成您想要的数据框:
GMC1 GMC2 Provider2
7 2 2.0 100.0
8 3 3.0 107.0
抱歉,回答有点罗嗦,但希望对您有所帮助!
合并确实是可行的方法。但是您必须在 groupby 中进行查询,以仅比较具有相同 GMC 值的提供商:
dataframe1.merge(dataframe2, left_on='GMC1', right_on='GMC2').groupby('GMC1').apply(
lambda df: df[~df['Provider2'].isin(df['Provider1'].values)]
)[['GMC1', 'GMC2', 'Provider2']].drop_duplicates().reset_index(drop=True)
符合预期
GMC1 GMC2 Provider2
0 2 2 100
1 3 3 107
按列和指标参数使用外部联接并按此新列过滤 _merge
:
df = dataframe1.merge(dataframe2,
left_on=['GMC1', 'Provider1'],
right_on=['GMC2', 'Provider2'],
how='right',
indicator=True)
df = (df.loc[df['_merge'].eq('right_only'), ['GMC1','GMC2','Provider2']]
.assign(GMC1 = lambda x: x['GMC2']))
print (df)
GMC1 GMC2 Provider2
1 2 2 100
4 3 3 107