关于熊猫部分字符串合并的另一个问题



我知道,有很多非常接近的例子,但我无法让它们对我起作用。我想根据部分字符串匹配从另一个数据帧添加一列:一个字符串包含在另一个字符串中,但不一定在开头。这里有一个例子:

df = pd.DataFrame({'citizenship': ['Algeria', 'Andorra', 'Bahrain', 'Spain']})    
df2 = pd.DataFrame({'Country_Name': ['Algeria, Republic of', 'Andorra', 'Kingdom of Bahrain', 'Russia'], 
'Continent_Name': ['Africa', 'Europe', 'Asia', 'Europe']})

df应该根据字符串match/merge从df2获取大陆,并将其附加到每个"公民身份"。我一直在尝试应用这里提到的解决方案Pandas:在部分字符串匹配上加入,就像ExcelVLOOKUP一样,但无法使其在中工作

def get_continent(x):
return df2.loc[df2['Country_Name'].str.contains(x), df2['Continent_Name']].iloc[0]
df['Continent_Name'] = df['citizenship'].apply(get_continent)

但它给了我一个关键错误

KeyError: "None of [Index(['Asia', 'Europe', 'Antarctica', 'Africa', 'Oceania', 'Europe', 'Africa',n       'North America', 'Europe', 'Asia',n       ...n       'Asia', 'South America', 'Oceania', 'Oceania', 'Asia', 'Africa',n       'Oceania', 'Asia', 'Asia', 'Asia'],n      dtype='object', length=262)] are in the [columns]"

有人知道这里发生了什么吗?

我可以在您的问题中看到代码的两个问题:

  1. 在函数返回行中,您需要删除df2.loc的第二个位置参数中的df2[]位,以将列名保留为字符串:df2.loc[df2['Country_Name'].str.contains(x), 'Continent_Name'].iloc[0]
  2. 然后,来自链接答案的代码似乎只有在"one_answers"之间总是匹配时才起作用;国家名称";在df2中;公民身份";在df中

因此这适用于例如:

df = pd.DataFrame({'citizenship': ['Algeria', 'Andorra', 'Bahrain', 'Spain']})    
df2 = pd.DataFrame({'Country_Name': ['Algeria', 'Andorra', 'Bahrain', 'Spain'], 
'Continent_Name': ['Africa', 'Europe', 'Asia', 'Europe']})

def get_continent(x):
return df2.loc[df2['Country_Name'].str.contains(x), 'Continent_Name'].iloc[0]
df['Continent_Name'] = df['citizenship'].apply(get_continent)
#   citizenship Continent_Name
# 0    Algeria  Africa
# 1    Andorra  Europe
# 2    Bahrain  Asia
# 3    Spain    Europe

如果你想让原始代码发挥作用,你可以放一个try/except:

df = pd.DataFrame({'citizenship': ['Algeria', 'Andorra', 'Bahrain', 'Spain']}) 
df2 = pd.DataFrame({'Country_Name': ['Algeria, Republic of', 'Andorra', 'Kingdom of Bahrain', 'Russia'], 
'Continent_Name': ['Africa', 'Europe', 'Asia', 'Europe']})
def get_continent(x):
try:
return df2.loc[df2['Country_Name'].str.contains(x), 'Continent_Name'].iloc[0]
except IndexError:
return None
df['Continent_Name'] = df['citizenship'].apply(get_continent)

#   citizenship Continent_Name
# 0  Algeria      Africa
# 1  Andorra      Europe
# 2  Bahrain      Asia
# 3  Spain        None

实现这一点的一种方法是在df2中创建一个citizenship列,并使用它将数据帧连接在一起。我认为制作本专栏最简单的方法是使用regex。

citizenship_list = df['citizenship'].unique().tolist()
citizenship_regex = r"(" + r"|".join(citizenship_list) + r")"
df2["citizenship"] = df2["Country_Name"].str.extract(citizenship_regex).iloc[:, 0]
joined_df = df.merge(df2, on=["citizenship"], how="left")
print(joined_df)

然后,您可以减少这种情况,只选择所需的列。

此外,您可能希望通过在citizenshipCountry_Name列上运行df['citizenship'] = df['citizenship'].str.lower()来清理它们,这样就不会因为大小写而丢失某些内容。

最新更新