如果字符串与列表中的字符串匹配,我该如何从句子中删除字符串?

5

我有一个包含像这样的句子的 pandas.Series

0    mi sobrino carlos bajó conmigo el lunes       
1    juan antonio es un tio guay                   
2    voy al cine con ramón                         
3    pepe el panadero siempre se porta bien conmigo
4    martha me hace feliz todos los días 

另一方面,我有一个像这样的名字姓氏列表:

l = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

我想将系列中的句子与名单中的姓名匹配。实际数据比这个例子要大得多,所以我认为逐个比较系列和名单中的元素效率不高,因此我创建了一个包含所有姓名字符串的大字符串,如下所示:

'|'.join(l)

我试图创建一个布尔掩码,后来可以通过true或false值索引包含在名称列表中的句子,如下所示:

series.apply(lambda x: x in '|'.join(l))

但它返回:

0    False
1    False
2    False
3    False
4    False

这显然是不好的。
我也尝试使用 str.contains(),但它的行为与我的预期不同,因为该方法会查看系列中是否存在名称列表中的任何子字符串,这不是我所需要的(即我需要精确匹配)。
请问您能否指点我正确的方向?
非常感谢您提前的帮助。

1
我不知道Panda是什么,但你可以使用正则表达式,尽管它可能会更重。 - Aurele Collinet
当然可以,但我不精通正则表达式,如果您提供一个可用的正则表达式,我可以尝试一下 :) - Miguel 2488
@everyone 感谢大家!!你们提供的所有支持让我感到不知所措。感谢你们的合作:D - Miguel 2488
6个回答

3

如果需要精确匹配,您可以使用单词边界:

series.str.contains('|'.join(rf"\b{x}\b" for x in l))

使用生成器推导式和筛选器只过滤掉拆分文本中不匹配的值,以通过列表删除值:

series = series.apply(lambda x: ' '.join(y for y in x.split() if y not in l))
print (series)
                            
0                mi sobrino bajó conmigo el lunes
1                                  es un tio guay
2                           voy al cine con ramón
3  pepe el panadero siempre se porta bien conmigo
4             martha me hace feliz todos los días

这里的 rf 是什么意思? - bigbounty
1
哦,不错啊,我不知道我们可以把它们结合起来。+1 - bigbounty
1
再次感谢Jezrael。您能否提供一些关于您的代码的更多信息?谢谢。 - Miguel 2488
@Miguel2488 - 当然,给我一些时间。 - jezrael
@Miguel2488 - 对于第二个问题,您可以通过.split()将值按空格拆分 - 默认分隔符是空格。然后使用推导式来迭代每个拆分的值,并测试是否不在列表中,因此从列表中删除匹配的值。最后使用join为过滤列表的值添加空格。 - jezrael
显示剩余2条评论

1
import re

data = ["mi sobrino carlos bajó conmigo el lunes", "juan antonio es un tio guay", "martha me hace feliz todos los días"]

regexs = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

for regex in regexs:

    for sentence in data:

        if re.match(regex, sentence):

            print True
        
        else:

            print False

我想一些简单的东西可能会起作用。
参考:https://docs.python.org/fr/3/library/re.html

请注意编码,西班牙语应该是UTF-8。 - Aurele Collinet
只需使用"^.juan.$"进行完全匹配。 - Aurele Collinet

1

正则表达式用于检查单词是否位于开头、结尾或中间

df = pd.DataFrame({'texts': [
                             'mi sobrino carlos bajó conmigo el lunes',
                             'juan antonio es un tio guay',
                             'voy al cine con ramón',
                             'pepe el panadero siempre se porta bien conmigo',
                             'martha me hace feliz todos los días '
                             ]})

names = ['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos']

pattern = "|".join([f"^{s}|{s}$|\\b{s}\\b" for s in names])

df[df.apply(lambda x: 
            x.astype(str).str.contains(pattern, flags=re.I)).any(axis=1)]

1
一个选项是集合的交集:
l = set(['juan', 'antonio', 'esther', 'josefa', 'mariano', 'cristina', 'carlos'])
s.apply(lambda x: len(set(x.split()).intersection(l))>0)

1

对于精确匹配,请尝试;

df.text.str.contains("|".join(l))

否则,只需使用正则表达式将子字符串替换为''。使用列表解析调用substring
df.replace(regex=[x for x in l], value='')
                          

                                   text
0               mi sobrino  bajó conmigo el lunes
1                                  es un tio guay
2                           voy al cine con ramón
3  pepe el panadero siempre se porta bien conmigo
4             martha me hace feliz todos los días

1
如果您想要更灵活地处理内容,您可以使用以下自定义的exact_match函数:
import re 

def exact_match(text, l=l):
    return bool(re.search('|'.join(rf'\b{x}\b' for x in l), text))

series.apply(exact_match)

输出:

0     True
1     True
2    False
3    False
4    False
dtype: bool

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