使用正则表达式匹配数据框中的列

时间:2019-08-12 16:32:54

标签: pandas dataframe

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

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

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列的名字并将其与相应的列匹配。

       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

先谢谢您!我遇到了这个问题的死胡同,无法找到一种方法来使它工作。

1 个答案:

答案 0 :(得分:0)

您实际上不需要在第二个数据框中定义正则表达式。 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')

与上面的输出相同。请注意,此版本可能会限制您可以使用的药物数量。如果您有数百种毒品,则可能会遇到问题,因为在这种情况下,正则表达式字符串会变长。但是此版本更清晰,并且在药物名称中还支持空格。 如果您可以设计出一个模式,从而能够正确切出所有药物名称,我建议您使用第一种方法。例如。如果您可以发现一个在药品名称后面的图案,则可以使用它来更容易地剪掉药品名称。