【问题标题】:Python matching various keyword from dictionary issuesPython匹配字典问题中的各种关键字
【发布时间】:2021-03-13 12:49:53
【问题描述】:

我有一个复杂的文本,我在其中对存储在字典中的不同关键字进行分类:

    text = 'data-ls-static="1">Making Bio Implants, Drug Delivery and 3D Printing in Medicine,MEDICINE</h3>'

    sector = {"med tech": ['Drug Delivery' '3D printing', 'medicine', 'medical technology', 'bio cell']}

这可以成功找到我的关键字并对其进行分类,但有一些限制:

    pattern = r'[a-zA-Z0-9]+'

    [cat for cat in sector if any(x in re.findall(pattern,text) for x in sector[cat])]

我无法解决的限制是:

  1. 例如,以空格分隔的“Drug Delivery”等关键字无法识别,因此无法分类。

  2. 我无法使模式不区分大小写,因为像 MEDICINE 这样的词无法识别。我尝试将 (?i) 添加到模式中,但它不起作用。

  3. 分类的关键字进入 pandas df,但它们被打印到 [] 中。我试图再次循环脚本以将它们取出,但它们仍然存在。

数据到 pandas df:

    ind_list = []
    for site in url_list:
        ind = [cat for cat in indication if any(x in re.findall(pattern,soup_string) for x in indication[cat])]
        ind_list.append(ind)

    websites['Indication'] = ind_list

当前输出:

Website                                  Sector                              Sub-sector                                 Therapeutical Area Focus URL status
0     url3.com                              [med tech]                                      []                                                 []          []         []
1     www.url1.com                    [med tech, services]                                      []                       [oncology, gastroenterology]          []         []
2     www.url2.com                    [med tech, services]                                      []                                        [orthopedy]          []         []

在输出中我得到了我想避免的 []。

你能帮我解决这些问题吗?

谢谢!

【问题讨论】:

  • 关于第 3 点,您能否提供示例代码如何将关键字设置为 pandas df ?
  • 查看我的分析结果(一些提示)如下。

标签: python regex pandas keyword keyword-search


【解决方案1】:

这里给你一些提示,很容易发现的问题:

  1. 为什么不能匹配用空格分隔的“Drug Delivery”等关键字?这是因为正则表达式模式r'[a-zA-Z0-9]+' 不匹配空格。如果您还想匹配空格,可以将其更改为r'[a-zA-Z0-9 ]+'(在9 之后添加一个空格)。但是,如果您想支持其他类型的空格(例如 \t、\n),则需要进一步更改此正则表达式模式。

  2. 为什么不支持不区分大小写的匹配?您的代码片段 any(x in re.findall(pattern,text) for x in sector[cat]) 要求 x 具有相同的大写/小写字母,因为两者都是 re.findall 的结果和 @ 987654327@。通过在 re.findall() 调用中设置 flags=re.I 甚至无法绕过此约束。建议您在检查之前将它们全部转换为相同的大小写。也就是说,例如在匹配之前将它们全部更改为小写:any(x in re.findall(pattern,text.lower()) for x.lower() in sector[cat]) 这里我们将.lower() 添加到textx.lower()

通过上述 2 项更改,它应该可以让您捕获一些分类的关键字。

实际上,对于这种特殊情况,您可能根本不需要使用正则表达式和re.findall。您可以检查例如sector[cat][i].lower()) in text.lower()。也就是说,将列表理解更改如下:

[cat for cat in sector if any(x in text.lower() for x in [y.lower() for y in sector[cat]])]

编辑

使用 2 字词组测试运行:

text = 'drug delivery'
sector = {"med tech": ['Drug Delivery', '3D printing', 'medicine', 'medical technology', 'bio cell']}
[cat for cat in sector if any(x in text.lower() for x in [y.lower() for y in sector[cat]])]

Output:       # Successfully got the categorizing keyword even with dictionary values of different upper/lower cases
['med tech']

text = 'Drug Store fast delivery'
[cat for cat in sector if any(x in text.lower() for x in [y.lower() for y in sector[cat]])]

Ouptput:    # Correctly doesn't match with extra words in between 

[]

【讨论】:

  • #SeaBean 感谢您的提示。是的,我解决了不敏感的问题。空间的东西仍然不起作用,这意味着像“Drug Delivery”这样的字典值匹配“Drug”或“Delivery”并且不够严格,
  • @Steven 这正是我的“实际上...”段落中的想法,您可以对其进行测试。 'Drug Delivery' in text 这样您就可以检查目标字符串中的整个短语(2 个单词)(在您的代码中称为 text 或 soup_string。
  • @Steven 在我的答案底部稍微修改了列表理解的示例代码。这应该更好地证明我所说的。
  • @Steven,还不够清楚。您的示例数据中没有名为 Indication 的列。正如您使用小数据测试我的最新代码可以将值提取到列表ind 中一样,问题应该出在代码的其他部分。建议做一个分而治之的测试,从一个应该有一些匹配的网站开始,然后检查提取到 ind 的值,然后跟踪你的程序,看看为什么它的值不能进入数据框。
  • @Steven 很高兴听到你快完成了!对于您提到的内容,您得到 [med tech] 而不仅仅是“med tech”,我认为这是因为您在每次循环迭代中提取的结果都在 ind 这是一个列表(因此 [...] 因为它是列表)。如果您只想获取字符串,您可以在附加到ind_list 之前连接存储在列表ind 中的字符串。例如,使用ind_text = ', '.join(ind) 之类的代码,然后使用ind_list.append(ind_text) 替换ind_list.append(ind)
【解决方案2】:

您能否尝试除正则表达式之外的其他方法,
当你有两个相似的匹配词时,我会建议difflib

【讨论】:

    【解决方案3】:

    findall 在这里非常浪费,因为您反复分解每个关键字的字符串。

    如果要测试关键字是否在字符串中:

    [cat for cat in sector if any(re.search(word, text, re.I) for word in sector[cat])]
    # Output: med tech
    

    【讨论】:

    • 感谢您的提示。它似乎效果更好,但是当我只想在字典中找到“药物递送”时,它匹配文本中的“药物”或“递送”等单个单词。
    • 你能添加你的测试用例吗?此文本与任何内容都不匹配:text = 'data-ls-static="1"&gt;Drug&lt;/h3&gt;'
    • 我更新了文本和字典。在文本中,您可以找到“Bio Implants”,在字典中的值之一是“bio cell”。在这种情况下,它匹配关键的医学技术,因为它找到了“bio”,但实际上我想匹配确切的值“bio cell”(如果有的话)。在这种情况下,它不应该匹配任何东西。
    猜你喜欢
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 2022-10-14
    • 2021-01-10
    • 2020-05-18
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    相关资源
    最近更新 更多