Как проверить, содержит ли строка одну из подстрок в списке, в пандах?

Есть ли какая-либо функция, которая будет эквивалентна комбинации df.isin() и df[col].str.contains()?

Например, скажем, у меня есть серия s = pd.Series(['cat','hat','dog','fog','pet']), и я хочу найти все места, где s содержит любое из ['og', 'at'], я бы хотел получить все, кроме 'pet'.

У меня есть решение, но оно довольно не элегантное

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

Есть лучший способ сделать это?

Ответ 1

Один из вариантов состоит в том, чтобы использовать символ regex |, чтобы попытаться сопоставить каждую из подстрок в словах в вашей серии 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.

Ответ 2

Вы можете использовать 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