如何测试一个字符串是否包含列表中的一个子字符串?

ari*_*ari 90 python string match dataframe pandas

是否有任何功能相当于df.isin()df[col].str.contains()?的组合?

例如,假设我有这个系列 s = pd.Series(['cat','hat','dog','fog','pet']),并且我想找到s包含任何内容的所有地方['og', 'at'],我想要获得除了宠物之外的一切.

我有一个解决方案,但它相当不优雅:

searchfor = ['og', 'at']
found = [s.str.contains(x) for x in searchfor]
result = pd.DataFrame[found]
result.any()
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

Ale*_*ley 168

一种选择就是使用正则表达式|字符来尝试匹配系列中单词中的每个子字符串s(仍然使用str.contains).

您可以通过加盟的话构建正则表达式searchfor|:

>>> searchfor = ['og', 'at']
>>> s[s.str.contains('|'.join(searchfor))]
0    cat
1    hat
2    dog
3    fog
dtype: object
Run Code Online (Sandbox Code Playgroud)

作为@AndyHayden在评论中指出的下方,照顾,如果你的子有特殊字符,如$^要逐字匹配.这些字符在正则表达式的上下文中具有特定含义,并将影响匹配.

您可以通过以下方式转义非字母数字字符,使子字符串列表更安全re.escape:

>>> import re
>>> matches = ['$money', 'x^y']
>>> safe_matches = [re.escape(m) for m in matches]
>>> safe_matches
['\\$money', 'x\\^y']
Run Code Online (Sandbox Code Playgroud)

使用时,此新列表中的字符串将逐字匹配每个字符str.contains.

  • 你需要注意的一件事是,如果searchfor中的字符串有特殊的正则表达式字符(你可以[用re.escape映射](http://stackoverflow.com/questions/280435/escaping-regex-string-in-python )). (6认同)
  • 也许很好添加这个链接http://pandas.pydata.org/pandas-docs/stable/text.html#splitting-and-replacing-strings.从pandas 0.15开始,字符串操作更加容易 (4认同)
  • 在这种情况下,我知道我们使用“|” 对于 OR,我们如何使用 AND? (2认同)

l'L*_*L'l 37

您可以使用str.contains以下正则表达式单独使用OR (|):

s[s.str.contains('og|at')]
Run Code Online (Sandbox Code Playgroud)

或者您可以将系列添加到dataframe然后使用str.contains:

df = pd.DataFrame(s)
df[s.str.contains('og|at')] 
Run Code Online (Sandbox Code Playgroud)

输出:

0 cat
1 hat
2 dog
3 fog 
Run Code Online (Sandbox Code Playgroud)

  • AND 该怎么办? (3认同)
  • @JacoSolari 查看这个答案 /sf/ask/2590821411/ (3认同)
  • @詹姆斯是的,谢谢。这里的完成是该答案中得票最多的一行。`df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)` (3认同)

Gra*_*non 7

这是一个也可以使用的单行 lambda:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)
Run Code Online (Sandbox Code Playgroud)

输入:

searchfor = ['og', 'at']

df = pd.DataFrame([('cat', 1000.0), ('hat', 2000000.0), ('dog', 1000.0), ('fog', 330000.0),('pet', 330000.0)], columns=['col1', 'col2'])

   col1  col2
0   cat 1000.0
1   hat 2000000.0
2   dog 1000.0
3   fog 330000.0
4   pet 330000.0
Run Code Online (Sandbox Code Playgroud)

应用 Lambda:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)
Run Code Online (Sandbox Code Playgroud)

输出:

    col1    col2        TrueFalse
0   cat     1000.0      1
1   hat     2000000.0   1
2   dog     1000.0      1
3   fog     330000.0    1
4   pet     330000.0    0
Run Code Online (Sandbox Code Playgroud)

  • 我这样做了`df.loc[df.col1.apply(lambda x: True if any(i in x for i in searchfor) else False)]`并且进展顺利,谢谢。 (2认同)