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
попробуйте это регулярное выражение
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