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

时间:2014-10-26 20:23:37

标签: python string pandas dataframe match

是否有任何功能相当于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()

有更好的方法吗?

3 个答案:

答案 0 :(得分:121)

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

您可以将searchfor中的字加入|来构建正则表达式:

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

正如@AndyHayden在下面的评论中指出的那样,请注意您的子字符串是否包含$^这样的特殊字符,而这些字符要与字面匹配。这些字符在正则表达式的上下文中具有特定含义,并将影响匹配。

您可以使用re.escape转义非字母数字字符,使子字符串列表更安全:

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

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

答案 1 :(得分:31)

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

s[s.str.contains('og|at')]

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

df = pd.DataFrame(s)
df[s.str.contains('og|at')] 

<强>输出:

0 cat
1 hat
2 dog
3 fog 

答案 2 :(得分:2)

这是一个单行lambda,它也可以工作:

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

输入:

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

应用Lambda:

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

输出:

    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