正则表达式 - 将子字符串与字符串匹配
Posted
技术标签:
【中文标题】正则表达式 - 将子字符串与字符串匹配【英文标题】:Regex - Match substring with Strings 【发布时间】:2022-01-17 14:44:20 【问题描述】:我有 2 个数据框,我想要创建一个匹配的 ID 列表。有了这些信息,我可以稍后执行合并(合并不是我的问题的一部分,我只想找出如何正确匹配行)。
DF1
ID |
---|
123 |
123B |
234 |
234B |
456 |
456B |
asfdh5 |
45gh |
DF2
ID |
---|
123456 |
123B456 |
BBBER4 |
234567YT |
B9234BAA |
456XXA32 |
999GHF |
pp9985 |
88AVKVBD |
Desired Result - 我想得到一个匹配的字符串列表
Matches | |
---|---|
0 | 123 |
1 | 123B |
2 | NaN |
3 | 234 |
4 | 234B |
5 | 456 |
6 | NaN |
7 | NaN |
8 | NaN |
我当前使用的代码如下
df2['ID'].str.extract(fr"('|'.join(df1['ID'].values))", expand=False)
问题是这段代码与 DF1 中的 ID 不完全匹配,如果您在上面的 Desired Results 中看到索引 2,结果是 123B,但是我我只得到 123。
以下是我使用当前代码得到的结果。
Matches | |
---|---|
0 | 123 |
1 | 123 |
2 | NaN |
3 | 234 |
4 | 234 |
5 | 456 |
6 | NaN |
7 | NaN |
8 | NaN |
任何帮助将不胜感激。感谢您, 钱
【问题讨论】:
@DSteman 正确,对于索引 4,它应该是 234B 等。而我的代码只得到 123 和 234(在某些情况下我缺少 B) 【参考方案1】:您的问题是它在查找匹配项并返回第一个匹配项时从 DF1 的顶部进行检查。如果您按列中字符串的长度对数据框进行排序,则会返回最长的匹配项。
这应该可以解决您的问题:
# Sort by length of string
new_index = df1.ID.str.len().sort_values().index
df1 = df1.reindex(index = new_index[::-1]).reset_index(drop=True)
# Match strings
df2['ID'].str.extract(fr"('|'.join(df1['ID'].values))", expand=False)
【讨论】:
【参考方案2】:这种行为是预期的,因为“对于系列中的每个主题字符串,从正则表达式 pat 的第一个匹配中提取组。” (https://pandas.pydata.org/docs/reference/api/pandas.Series.str.extract.html)。所以你得到的是'123'而不是'123B',因为'123'是df1
系列中的第一个值,因此是第一个匹配项。
【讨论】:
【参考方案3】:您需要做的就是使用sorted(df1['ID'].values, key=len, reverse=True)
按长度降序对df1['ID']
值进行排序:
>>> df2['ID'].str.extract(fr"('|'.join(sorted(df1['ID'].values, key=len, reverse=True)))", expand=False)
0 123
1 123B
2 NaN
3 234
4 234B
5 456
6 NaN
7 NaN
8 NaN
Name: ID, dtype: object
您需要这个,因为 NFA 正则表达式引擎(Python 的 re
是)中更长的替代方案总是“获胜”,并且同一组中的所有其他替代方案甚至都没有被正则表达式引擎尝试。见Remember That The Regex Engine Is Eager。例如。你在你的正则表达式中高清123|123B
,所以123
在123B456
中匹配123
并返回了那个匹配,123B
没有尝试替代,等等。
【讨论】:
谢谢。当我尝试使用上面的数据执行合并时(我在代码中将其称为键),我收到一个键错误。你知道这是为什么吗?df1 = pd.merge(df1, df2[['Name', 'Company']], left_on=['ID'], # right_on=[key], how='left').drop_duplicates().fillna('')
请注意,DF2 也有一列包含我正在尝试合并到 DF1 中的公司信息
@PythonBeginner 让我们一一处理问题。如果以上解决了问题,请告知。这个后续问题只有在您提供所有数据后才能回答,并且应该是一个单独的问题。以上是关于正则表达式 - 将子字符串与字符串匹配的主要内容,如果未能解决你的问题,请参考以下文章