Python: 检查关键词在字符串中以空格分隔出现的情况

4
我有两个数据框 - 一个包含自由文本说明,另一个是主词典。我正在尝试检查主词典中的单词是否以任何格式出现在文本说明中 - 例如,如果主关键字是123456789,它可能出现在用户文本中,如12345 6789123 456 789。关键字可以是数字也可以是字母数字混合。
我已经尝试从文本说明中删除空格,并使用in函数进行检查,但这种方法还会匹配噪声。例如,它还将匹配b123 4567 89klx。我想仅匹配整个关键字被拆分并作为多个单词给出,而不是在不同单词之间。
我现在的代码:
def matcher(x,word_dict):
    match=""
    for i in list(dict.fromkeys(word_dict)):
        if i.replace(" ", "").lower() in x.replace(" ", "").lower():
            if(match==""):
                match=i
            else:
                match=match+"_"+i
    return match


import pandas as pd
df = pd.DataFrame({'ID' : ['1', '2', '3', '4','5'], 
        'Text' : ['sample 123 45 678 text','sample as123456 text','sample As123 456','sample bas123456 text','sample bas123 456ts text']}, 
                  columns = ['ID','Text'])

master_dict= pd.DataFrame({'Keyword' : ['12345678','as123456']}, 
                  columns = ['Keyword'])

df['Match']=df['Text'].apply(lambda x: matcher(x,master_dict.Keyword))


Expected Output
    ID  Text                     Match
0   1   sample 123 45 678 text   12345678
1   2   sample as123456 text     as123456
2   3   sample As123 456         as123456
3   4   sample bas123456 text    NA
4   5   sample bas123 456ts text NA

任何线索都将有助于。提前感谢。

2个回答

1
你可以使用Pandas对我先前的解决方案进行改编:
import pandas as pd
import numpy as np
import re

df = pd.DataFrame({'ID' : ['1', '2', '3', '4','5'], 
        'Text' : ['sample 123 45 678 text','sample as123456 text','sample As123 456','sample bas123456 text','sample bas123 456ts text']}, 
        columns = ['ID','Text'])
master_dict= pd.DataFrame({'Keyword' : ['12345678','as123456']}, 
                  columns = ['Keyword'])

words = master_dict['Keyword'].to_list()
words_dict = { f'g{i}':item for i,item in enumerate(words) } 
rx = re.compile(r"(?i)\b(?:" + '|'.join([ r'(?P<g{}>{})'.format(i,"[\W_]*".join([c for c in item])) for i,item in enumerate(words)]) + r")\b")
print(rx.pattern)

def findvalues(x):
    m = rx.search(x)
    if m:
        return [words_dict.get(key) for key,value in m.groupdict().items() if value][0]
    else:
        return np.nan

df['Match'] = df['Text'].apply(lambda x: findvalues(x))

模式是

(?i)\b(?:(?P<g0>1[\W_]*2[\W_]*3[\W_]*4[\W_]*5[\W_]*6[\W_]*7[\W_]*8)|(?P<g1>a[\W_]*s[\W_]*1[\W_]*2[\W_]*3[\W_]*4[\W_]*5[\W_]*6))\b

请查看正则表达式演示。基本上,它是一个带有\b(?:关键字1|关键字2|...|关键字N)\b的正则表达式,其中[\W_]*(匹配任何零个或多个非数字字母字符)在每个字符之间。由于\b,单词边界,关键字仅作为整个单词匹配。对于您确认为数字或字母数字的关键字,它将起作用。

演示输出:

>>> df
  ID                      Text     Match
0  1    sample 123 45 678 text  12345678
1  2      sample as123456 text  as123456
2  3          sample As123 456  as123456
3  4     sample bas123456 text       NaN
4  5  sample bas123 456ts text       NaN
>>> 

嗨Wiktor,我有的数据集相当庞大,这段代码需要很长时间才能运行。有优化的空间吗?我尝试将主字典分割并多次运行它,想要检查是否有更好的方法来处理它。 - MJ17
@MJ17 我认为这种方法没有太多的空间。如果你知道关键字的各个部分之间只能有空格,那么请用 [ ]* 替换 [\W_]* - Wiktor Stribiżew

0
在函数中检查,如果该字符串是另一个字符串的一部分,将获得true。我认为应该使用以下方法进行检查:
if string == keyword:

如果您处理了空格,那么它将会得到您想要的结果,因此如果结果与关键字不完全相等,则应返回 False。

请让我知道我是否正确理解了您的请求以及它是否有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接