【问题标题】: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)

标签: python regex pandas


【解决方案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,所以123123B456中匹配123并返回了那个匹配,123B没有尝试替代,等等。

      【讨论】:

      • 谢谢。当我尝试使用上面的数据执行合并时(我在代码中将其称为键),我收到一个键错误。你知道这是为什么吗? df1 = pd.merge(df1, df2[['Name', 'Company']], left_on=['ID'], # right_on=[key], how='left').drop_duplicates().fillna('') 请注意,DF2 也有一列包含我正在尝试合并到 DF1 中的公司信息
      • @PythonBeginner 让我们一一处理问题。如果以上解决了问题,请告知。这个后续问题只有在您提供所有数据后才能回答,并且应该是一个单独的问题。
      猜你喜欢
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      相关资源
      最近更新 更多