【问题标题】:Matching columns in dataframe using regex使用正则表达式匹配数据框中的列
【发布时间】:2019-08-12 16:32:54
【问题描述】:

希望执行正则表达式函数以将数据框的列与另一列的第一个单词匹配。数据框是从不同来源收集的,因此药物名称相似但不完全匹配。如果您忽略大小写并匹配第一个单词,它们确实匹配。

我有两个数据框:一个包含药物名称,另一个包含药物名称列表及其各自的价格。出于示例目的,水果被添加到药物名称中。

Dataframe A  
      drug
0   drug1 apple
1   drug2 orange
2   drug3 lemon
3   drug4 peach

Dataframe B
   drugB    price   Regex
0  DRUG2     2  ^([\w\-]+)
1  DRUG4     4  ^([\w\-]+)
2  DRUG3     3  ^([\w\-]+)
3  DRUG1     1  ^([\w\-]+)

我希望像这样使用 Regex 列将数据框 A 附加到 B。希望使用药物列的名字并将其与相应的列相匹配。

       drug         drugB   price   Regex
0   drug1 apple     DRUG1     1  ^([\w\-]+)
1   drug2 orange    DRUG2     2  ^([\w\-]+)
2   drug3 lemon     DRUG3     3  ^([\w\-]+)
3   drug4 peach     DRUG4     4  ^([\w\-]+)

基于以下 stackoverflow 问题,我受到启发以这种方式尝试:How to merge pandas table by regex

提前感谢您!我在这个问题上遇到了死胡同,想不出办法让它工作。

【问题讨论】:

  • 根据您的描述,您可能需要.str.split().str[0] 用于DataFrameA,.str.lower() 用于DataFrame B,然后您可以完全匹配。

标签: pandas dataframe


【解决方案1】:

您实际上不需要在第二个数据框中定义正则表达式。顺便说一句,ALollz 是对的。您可以轻松拆分字符串,但我想您需要它的目的更复杂,并且可能您的药物名称包含空格。

带有通用正则表达式的简单版本

如果您可以设法定义一个与所有药物名称匹配的通用正则表达式,则可以使用以下代码:

df_A['drugA']= df_A['drug'].str.extract('^\s*(?P<drugA>[\w\-]*)')['drugA'].str.upper()
df_A.merge(df_B[['drugB', 'price']], left_on='drugA', right_on='drugB', how='left')

只需将后面的表达式替换为您需要的正则表达式即可。输出将是:

           drug  drugA  drugB  price
0   drug1 apple  DRUG1  DRUG1      1
1  drug2 orange  DRUG2  DRUG2      2
2   drug3 lemon  DRUG3  DRUG3      3
3   drug4 peach  DRUG4  DRUG4      4

生成正则表达式的版本

drug_list= df_B['drugB'].to_list()
# sort the drug names by length descending
# to make sure we get the longest match
# --> relevant only if a drug name is included
#     fully in another name
#     Like "Aspirin" & "Aspirin plus C"
drug_list.sort(key=lambda drug: len(drug), reverse=True)

drug_pattern= '^\s*(?P<drugA>{drug_list})'.format(drug_list='|'.join(drug_list))

df_A['drugA']= df_A['drug'].str.extract(drug_pattern, re.I)['drugA'].str.upper()

df_A.merge(df_B[['drugB', 'price']], left_on='drugA', right_on='drugB', how='left')

这与上面的输出相同。请注意,此版本可能会限制您可以使用的药物数量。如果你有数百种药物,它可能会遇到问题,因为在这种情况下正则表达式字符串会变长。但这个版本更清晰,还支持药物名称中的空格。 如果您可以制定出一种能够正确删除所有药物名称的模式,我肯定会建议使用第一种方法。例如。如果您能发现药物名称之后的模式,您可以使用它更轻松地删除药物名称。

【讨论】:

  • 谢谢!您对我提供的药物名称比我提供的示例更难的药物名称是正确的。您的正则表达式示例效果非常好!但是药物名称格式存在太多差异,我不得不选择 Alollz 的答案并手动更改难以为其创建正则表达式的行。
猜你喜欢
  • 1970-01-01
  • 2014-08-04
  • 2012-11-13
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 2020-06-09
相关资源
最近更新 更多