如何从列值中排除带前缀的子字符串

How to exclude prefixed substrings from column values

我的目标是排除前缀为 No 的行,例如我对 commerce 这个词感兴趣,那么我有保留所有行包含 commerce 并排除 no commerce。我正在寻找通用解决方案

data = {
'description':[
    'Commerce foo', 
    'foo commercial',
    'foo no commercial',
    'foo commercial boo',
    'No commerce',
    'foo restaurant',
    'boo no restaurant']
}

df = pd.DataFrame(data)

    ______________________
    | description        |
__________________________
| 0 | Commerce foo       |
| 1 | foo commercial     |
| 2 | foo no commercial  |
| 3 | foo commercial boo |
| 4 | No commerce        |
| 5 | foo restaurant     |
| 6 | boo no restaurant  |
__________________________

我试过了(没用)

search = ['restaurant', 'commerce', 'commercial']

df['description'].str.findall(f'̂̂̂^(?<=no\s)({"|".join(search)})', flags=re.IGNORECASE)

我在找什么

    ______________________
    | description        |
__________________________
| 0 | Commerce foo       |
| 1 | foo commercial     |
| 3 | foo commercial boo |
| 5 | foo restaurant     |
__________________________

该模式当前以 ^(?<=no\s) 开头,它断言从字符串的开头开始应该有 no 后跟一个直接在左侧的空白字符。那将不匹配。

如果要过滤行,可以使用str.contains代替findall。

您可以删除锚点 ^ 并将断言更改为 (?<!no\s) 什么将断言没有 no 后跟一个空白字符直接到左侧并添加单词边界向左和向右移动以防止部分单词匹配。

仅对于一场比赛,您可以将捕获组更改为非捕获组(?:

如果打印图案,它看起来像

\b(?<!no\s)(?:restaurant|commerce|commercial)\b

看到一个regex demo

data = {
    'description':[
        'Commerce foo',
        'foo commercial',
        'foo no commercial',
        'foo commercial boo',
        'No commerce',
        'foo restaurant',
        'boo no restaurant']
}

df = pd.DataFrame(data)
search = ['restaurant', 'commerce', 'commercial']
print(df[df['description'].str.contains(fr'\b(?<!no\s)(?:{"|".join(search)})\b', flags=re.IGNORECASE)])

输出

          description
0        Commerce foo
1      foo commercial
3  foo commercial boo
5      foo restaurant