我有2个dataFrames。
DF1:
index ID City Region 2City
1 23 Moscow Msk
2 34 Obninsk Msk Msk
3 56 Spb
4 17 Tula Spb
DF2:
index City Office
1 Msk Msk
2 Spb Spb
3 Tula Msk
4 Moscow Msk
我想获得以下df:
index ID City Region 2City Office
1 23 Moscow Msk Msk
2 34 Obninsk Msk Msk Msk
3 56 Spb Spb
4 17 Tula Spb Msk
因此,它会检查来自df2的'office'
与来自df1的'City'
,'Region'
,'2City'
匹配。
如果我找到'office'
的{{1}},我就会停止搜索。因此,'City'
列具有优先权,然后是'City'
,然后是'Region'
。
我知道如何使用3 '2City'
执行此操作,但我希望有更好的选择。
答案 0 :(得分:1)
通常使用join
(默认为左连接)或merge
(必须指定how='left'
)在Pandas中执行VLOOKUP。
在您的情况下,您尝试基于三列查找值。一种方法是使用or
获取第一个非空值。
>>> (df1
.assign(temp = [region or two_city or city
for region, two_city, city in zip(df1.Region, df1['2City'], df1.City)])
.merge(df2, how='left', right_on='City', left_on='temp', suffixes=['', '_'])
.drop(['temp', 'City_'], axis=1))
ID City Region 2City Office
0 23 Moscow Msk None Msk
1 34 Obninsk Msk Msk Msk
2 56 None None Spb Spb
3 17 Tula Spb None Msk
答案 1 :(得分:0)
您可以将两个DataFrame合并到pd.merge
,但据我了解,您实际上想要合并df1
中的不同列。一种可行的方法是添加一个额外的列,如果可用,则使用'City'
的值(否则为'region'
或'2City'
)。
import pandas as pd
df1['Office'] = df1.City.fillna(df1.Region).fillna(df1['2City'])
df = pd.merge(df1, df2.reindex(columns='Office'), on='Office')
您不指定在任一DataFrame中是否缺少值。如果是这样,您可以使用how
的{{1}}参数控制其处理。
答案 2 :(得分:0)
没有for
循环:
cols = ['City', 'Region', '2City']
df1[cols].applymap(lambda x: df2.set_index('City')['Office'].get(x)) \
.apply(lambda row: row[row.first_valid_index()], axis=1)
我将City
设置为df2
的索引,以便使用get
方法查找值。在使用applymap
按元素查找值后,我找到first_valid_index
的第一个有效答案。
答案 3 :(得分:0)
import pandas as pd
df1 = pd.DataFrame([[23, 'Moscow', 'Msk', ''],
[34, 'Obninsk', 'Msk', 'Msk'],
[56, '', '', 'Spb'],
[17, 'Tula', 'Spb', '']],
columns=['ID', 'City', 'Region', '2City'])
df2 = pd.DataFrame([['Msk', 'Msk'],
['Spb', 'Spb'],
['Tula', 'Msk'],
['Moscow', 'Msk']],
columns=['City', 'Office'])
df = pd.concat([df1.loc[df1[x].isin(df2['City']), x] for x in ['City', 'Region', '2City']])
df1['Join'] = df.groupby(df.index).first()
output = df1.merge(df2, left_on='Join', right_on='City', how='right')
此时,名为“output”的pandas.DataFrame
将包含一个名为“Office”的列,该列已正确索引以与df1匹配。你可以这样做:
df1['Office'] = output['Office']
这将为您提供所请求的DataFrame以及附加列“Join”,您可以通过以下方式删除:
df1.drop('Join', axis=1, inplace=True)
这里的OP基本上要做三个单独的合并 - 一个在df1
的每个列“City”,“Region”和“2City”上。因此,如果没有一些体操,使用基本的pandas.DataFrame
操作就不容易做到这一点。我只是隐藏了列表理解中的for循环,但它仍然存在。