提问人:Benjamin Allen 提问时间:9/29/2023 更新时间:10/2/2023 访问量:64
数据帧中的字符串与具有多个匹配选项的其他数据帧的文本匹配
Literal match of strings in dataframe to other dataframe with multiple match options
问:
我有一个数据帧 (df),其值位于“国家/地区”列中,我希望使用另一个名为“country_codes”的数据帧对其进行标准化。df 中的值可以与“country_codes”中的任何项目匹配,但生成的数据帧应包含相应的 country_code['country'] 值,即标准值。
该代码主要工作,并且确实返回标准国家/地区值,但正则表达式与确切的字符串不匹配。它匹配得太少(在本例中为:“Example1”)。
附加问题:是否有可能在最终输出数据帧中保留“年份”数据,而不指定名称“年份”,因为可能有多个浮点列。
下面显示了函数和所需的输出:
def match_country_codes(df, country_codes):
# Create a regex pattern to match whole words
pattern = '|'.join(rf'\b{re.escape(c)}\b' for c in country_codes[['country', 'alpha1', 'alpha2']].values.flatten())
# new column for matches between pattern and df['country'] items
df['matched_country'] = df['country'].str.extract(f'({pattern})', flags=re.IGNORECASE)
# Merge with 'country_codes' dataframe to get the full country names
# merge over 3 frames for all columns
df1 = df.merge(country_codes, left_on='matched_country', right_on='country', how='left')
df2 = df.merge(country_codes, left_on='matched_country', right_on='alpha1', how='left')
df3 = df.merge(country_codes, left_on='matched_country', right_on='alpha2', how='left')
dataframes = [df1, df2, df3]
# merge all dataframes together on '[['country_y']]'
result = reduce(merge_dataframes, dataframes)
# Drop rows with None or NaN values in the 'country_y' column
result = result.dropna(subset=['country_y'])
# return result
return result
示例数据帧:
df = pd.DataFrame({'country': ['foobar', 'foo and bar', 'Example1 and', 'PQR'],
'year':[2018, 2019, 'NA',2017]
})
country_codes = pd.DataFrame({'country': ['FooBar', 'Example1', 'foo and bar and foo', 'Example'],
'alpha1': ['foobar', 'Bosnia', 'ABC', 'DEF'],
'alpha2': ['GHI', 'JKL', 'MNO', 'PQR']
})
输出:
result = match_country_codes(df, country_codes)
result
期望输出:
data = {'country_y': ['FooBar', 'Example']
}
index_values = [0, 3]
desired_output = pd.DataFrame(data, index=index_values)
desired_output
谢谢
答:
1赞
Nick
9/30/2023
#1
对方法稍作修改:在每列上传入 DataFrame (using ),然后取每行值中的第一个非 NaN 值。join
country_codes
set_index
country
df['country_y'] = (df
.join(country_codes.set_index('country', drop=False), on='country', rsuffix='_1')
.join(country_codes.set_index('alpha1'), on='country', rsuffix='_2')
.join(country_codes.set_index('alpha2'), on='country', rsuffix='_3')
[['country_1', 'country_2', 'country_3']]
.groupby(lambda r: 'X', axis=1)
.first()
)
df = df.dropna(subset='country_y')
对于此示例数据:
data = {
'country': [None, 'foobar', 'foo and bar', 'Example1 and', 'PQR', 'Example', 'Bosnia', None, 'JKL', 'foobar'],
'year': [None, None, 2018, 2019, 2017, 2020, 2017, None, 2019, 2019]
}
df = pd.DataFrame(data)
输入:
country year
0 None NaN
1 foobar NaN
2 foo and bar 2018.0
3 Example1 and 2019.0
4 PQR 2017.0
5 Example 2020.0
6 Bosnia 2017.0
7 None NaN
8 JKL 2019.0
9 foobar 2019.0
输出将为:
country year country_y
1 foobar NaN FooBar
4 PQR 2017.0 Example
5 Example 2020.0 Example
6 Bosnia 2017.0 Example1
8 JKL 2019.0 Example1
9 foobar 2019.0 FooBar
评论
0赞
Benjamin Allen
9/30/2023
谢谢,但如果有“NA”值,代码就会停止工作,即使它们被删除。''' df = pd。DataFrame({'country': [np.nan, np.nan, 'foobar', 'foo and bar', 'Example1 and', 'PQR'], 'year':[np.nan, np.nan, 2018, 2019, 'NA',2017] }) country_codes = pd.DataFrame({'country': ['FooBar', 'Example1', 'foo and bar and foo', 'Example'], 'alpha1': ['foobar', '波斯尼亚', 'ABC', 'DEF'], 'alpha2': ['GHI', 'JKL', 'MNO', 'PQR'] }) df = df.dropna() '''
0赞
Benjamin Allen
9/30/2023
它现在可以工作了:首先删除 NA 并在 DF['country'] 中重置索引。谢谢!
0赞
Nick
9/30/2023
@BenjaminAllen是的,我现在正在查看它,这是 中出现的索引排序问题,它似乎没有像文档所说的那样工作。您的建议绝对是一种解决方法,但我仍然会尝试弄清楚为什么会发生这种情况。join
0赞
Nick
9/30/2023
@BenjaminAllen很晚了,我早上再看一眼。我现在已经在答案中记下了这个问题。
0赞
Nick
10/1/2023
@BenjaminAllen问题不在于值,而在于 .如果先,代码将按预期工作。看我的编辑。NaN
country
drop_duplicates
评论
merge_dataframes
PQR