pandas dataframe str.содержит () и операции

DF (Pandas Dataframe) имеет три строки.

some_col_name
"apple is delicious"
"banana is delicious"
"apple and banana both are delicious"

df.col_name.str.contains("apple|banana")

поймает все строки:

"apple is delicious",
"banana is delicious",
"apple and banana both are delicious".

как подать заявку и оператор на str.содержит метод, так что он захватывает только строки, содержащие как apple & banana?

"apple and banana both are delicious"

Я хотел бы захватить строки, которые содержат 10-20 разных слов (виноград, арбуз ,ягода, апельсин,..., п.)

7 ответов


вы можете сделать это следующим образом:

df[(df['col_name'].str.contains('apple')) & (df['col_name'].str.contains('banana'))]

df = pd.DataFrame({'col': ["apple is delicious",
                           "banana is delicious",
                           "apple and banana both are delicious"]})

targets = ['apple', 'banana']

# Any word from `targets` are present in sentence.
>>> df.col.apply(lambda sentence: any(word in sentence for word in targets))
0    True
1    True
2    True
Name: col, dtype: bool

# All words from `targets` are present in sentence.
>>> df.col.apply(lambda sentence: all(word in sentence for word in targets))
0    False
1    False
2     True
Name: col, dtype: bool

вы также можете сделать это в стиле выражения regex:

df[df['col_name'].str.contains(r'^(?=.*apple)(?=.*banana)')]

затем вы можете построить свой список слов в строку регулярного выражения, например:

base = r'^{}'
expr = '(?=.*{})'
words = ['apple', 'banana', 'cat']  # example
base.format(''.join(expr.format(w) for w in words))

сделает:

'^(?=.*apple)(?=.*banana)(?=.*cat)'

тогда вы можете делать свои вещи динамически.


если вы хотите поймать как минимум два слова в предложении, возможно, это сработает (взяв подсказку от @Alexander):

target=['apple','banana','grapes','orange']
connector_list=['and']
df[df.col.apply(lambda sentence: (any(word in sentence for word in target)) & (all(connector in sentence for connector in connector_list)))]

выход:

                                   col
2  apple and banana both are delicious

если у вас есть более двух слов, чтобы поймать, которые разделены запятой',', чем добавить его в connector_list и изменить второе условие от всех до любого

df[df.col.apply(lambda sentence: (any(word in sentence for word in target)) & (any(connector in sentence for connector in connector_list)))]

выход:

                                        col
2        apple and banana both are delicious
3  orange,banana and apple all are delicious

это работает

df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)

попробуйте это регулярное выражение

apple.*banana|banana.*apple

код:

import pandas as pd

df = pd.DataFrame([[1,"apple is delicious"],[2,"banana is delicious"],[3,"apple and banana both are delicious"]],columns=('ID','String_Col'))

print df[df['String_Col'].str.contains(r'apple.*banana|banana.*apple')]

выход

   ID                           String_Col
2   3  apple and banana both are delicious

перечисление всех возможностей для больших списков является громоздким. Лучший способ-использовать reduce() и побитовое и оператор (&).

например, рассмотрим следующий фрейм данных:

df = pd.DataFrame({'col': ["apple is delicious",
                       "banana is delicious",
                       "apple and banana both are delicious",
                       "i love apple, banana, and strawberry"]})

#                                    col
#0                    apple is delicious
#1                   banana is delicious
#2   apple and banana both are delicious
#3  i love apple, banana, and strawberry

Предположим, мы хотели бы искать все следующее:

targets = ['apple', 'banana', 'strawberry']

мы можем сделать:

#from functools import reduce  # needed for python3
print(df[reduce(lambda a, b: a&b, (df['col'].str.contains(s) for s in targets))])

#                                    col
#3  i love apple, banana, and strawberry