我一直在寻找合并查询的帮助,但我不确定用最简洁的方式来表达我的问题,所以我们无法找到任何直接帮助的东西。
我希望使用左连接合并三列上的两个表,但是在第三个字段中有一些空条目,在这种情况下,我认为我实际上想要一个外连接 - 所以如果有一个匹配前两列,无论第三列中是否匹配,数据都将被连接。
df_A:
Competitor Product Type
A P1 X
A P2 X
A P2 Y
B P1 X
B P1 Y
df_B:
Competitor Product Type Value
A P1 X £5
A P2 X £10
A P2 Y £12
B P1 £15
我想使用Competitor,Product和Type字段对这两个表进行合并。但是,' Type'第二个表中的字段并不总是被填充,在这个例子中,我希望Value应用于表A中的所有类型,即:
Competitor Product Type Value
A P1 X £5
A P2 X £10
A P2 Y £12
B P1 X £15
B P1 Y £15
我可以使用代码成功合并前两列:
df_merge=pd.merge(df_A,df_B,how='left',on=['Competitor','Product'])
但是如果我添加第三列' Type',这只会填充所有列中具有匹配项的值,即:
Competitor Product Type Value
A P1 X £5
A P2 X £10
A P2 Y £12
B P1
B P1
有没有办法组合连接类型或任何其他方式来获得此解决方案?
答案 0 :(得分:3)
您可以在['Competitor','Product']
上合并:
df_merged = pd.merge(df_A, df_B, how='left', on=['Competitor','Product'])
然后选择类型相同的行
或者Type_y
是通配符值:
mask = (df_merged['Type'] == df_merged['Type_y']) | (df_merged['Type_y'] == '')
result = df_merged.loc[mask, ['Competitor','Product','Type','Value']]
例如,
import pandas as pd
df_A = pd.DataFrame({'Competitor': ['A', 'A', 'A', 'B', 'B'],
'Product': ['P1', 'P2', 'P2', 'P1', 'P1'],
'Type': ['X', 'X', 'Y', 'X', 'Y']})
df_B = pd.DataFrame({'Competitor': ['A', 'A', 'A', 'B'],
'Product': ['P1', 'P2', 'P2', 'P1'],
'Type': ['X', 'X', 'Y', ''],
'Value': ['£5', '£10', '£12', '£15']},)
df_merged = pd.merge(df_A, df_B, how='left', on=['Competitor','Product'],
suffixes=('','_y'))
mask = (df_merged['Type'] == df_merged['Type_y']) | (df_merged['Type_y'] == '')
result = df_merged.loc[mask, ['Competitor','Product','Type','Value']]
print(result)
产量
Competitor Product Type Value
0 A P1 X £5
1 A P2 X £10
4 A P2 Y £12
5 B P1 X £15
6 B P1 Y £15
可以使用
进行批评pd.merge(df_A, df_B, how='left', on=['Competitor','Product'])
是它可以生成许多不必要的行 - Type_x
不等于Type_y
的所有行。如果df_A
和df_B
很大,则可能导致过度使用内存。
为了解决这个问题,我们可以通过将df_B
分成两部分来更简约地使用内存:带有通配符值的行和没有通配符的行:
is_wild = pd.isnull(df_B['Type'])
df_notwild, df_wild = df_B.loc[~is_wild], df_B.loc[is_wild]
然后分别合并这两个部分。如果没有通配符值,我们可以
所有列的内部合并。当有通配符时,我们只想右键合并
['Competitor','Product']
:
df_merged1 = pd.merge(df_A, df_notwild, how='inner')
df_merged2 = pd.merge(df_A, df_wild, how='right', on=['Competitor','Product'],
suffixes=('','_y')).drop('Type_y', axis=1)
然后可以连接两个DataFrame以形成所需的结果:
result = pd.concat([df_merged1, df_merged2], ignore_index=True)
因此,为了节省内存,
import numpy as np
import pandas as pd
df_A = pd.DataFrame({'Competitor': ['A', 'A', 'A', 'B', 'B'],
'Product': ['P1', 'P2', 'P2', 'P1', 'P1'],
'Type': ['X', 'X', 'Y', 'X', 'Y']})
df_B = pd.DataFrame({'Competitor': ['A', 'A', 'A', 'B'],
'Product': ['P1', 'P2', 'P2', 'P1'],
'Type': ['X', 'X', 'Y', np.nan],
'Value': ['£5', '£10', '£12', '£15']},)
is_wild = pd.isnull(df_B['Type'])
df_notwild, df_wild = df_B.loc[~is_wild], df_B.loc[is_wild]
df_merged1 = pd.merge(df_A, df_notwild, how='inner')
df_merged2 = pd.merge(df_A, df_wild, how='right', on=['Competitor','Product'],
suffixes=('','_y')).drop('Type_y', axis=1)
result = pd.concat([df_merged1, df_merged2], ignore_index=True)
print(result)
产生与上面第一种方法相同的结果。