如何在pandas中测试字符串是否包含列表中的子串?
有没有什么函数可以同时实现 df.isin()
和 df[col].str.contains()
的功能呢?
举个例子,我有一个序列
s = pd.Series(['cat','hat','dog','fog','pet'])
,我想找出所有包含 ['og', 'at']
的地方,我希望得到除了 'pet' 以外的所有项。
我有一个解决方案,但感觉不太优雅:
searchfor = ['og', 'at']
found = [s.str.contains(x) for x in searchfor]
result = pd.DataFrame[found]
result.any()
有没有更好的方法呢?
4 个回答
1
我也遇到过同样的问题。为了简单明了,你可以在每个条目之间加上一个|
,比如fieldname.str.contains("cat|dog")
这样就可以用了。
15
这里有一个可以用一行代码写成的简单函数,也能正常工作:
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
应用这个简单函数:
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
107
你可以单独使用 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
446
一种方法是使用正则表达式中的 |
符号,来尝试匹配你在 Series 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
一起使用时,会逐个字符地进行字面匹配。