我知道,有很多非常接近的例子,但我无法让它们对我起作用。我想根据部分字符串匹配从另一个数据帧添加一列:一个字符串包含在另一个字符串中,但不一定在开头。这里有一个例子:
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]"
有人知道这里发生了什么吗?
我可以在您的问题中看到代码的两个问题:
- 在函数返回行中,您需要删除
df2.loc
的第二个位置参数中的df2[]
位,以将列名保留为字符串:df2.loc[df2['Country_Name'].str.contains(x), 'Continent_Name'].iloc[0]
- 然后,来自链接答案的代码似乎只有在"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)
然后,您可以减少这种情况,只选择所需的列。
此外,您可能希望通过在citizenship
和Country_Name
列上运行df['citizenship'] = df['citizenship'].str.lower()
来清理它们,这样就不会因为大小写而丢失某些内容。