pandas dataframe str.contains () AND operation

df (Pandas Dataframe) tiene tres filas.

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

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

Atrapará todas las filas:

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

¿Cómo aplico el operador AND en el método str.contains, de modo que solo tome cuerdas que contengan AMBAS manzanas y bananos?

 "apple and banana both are delicious" 

Me gustaría agarrar cuerdas que contienen 10-20 palabras diferentes (uva, sandía, baya, naranja, …, etc.)

Puedes hacerlo de la siguiente manera:

 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 

También puedes hacerlo en el estilo de expresión regex:

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

Luego, puede construir su lista de palabras en una cadena de expresiones regulares como:

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

renderizará:

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

Entonces puedes hacer tus cosas dinámicamente.

Esto funciona

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

Si desea capturar en el mínimo al menos dos palabras en la oración, tal vez esto funcione (tomando la sugerencia de @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)))] 

salida:

  col 2 apple and banana both are delicious 

Si tiene más de dos palabras para capturar que están separadas por comas ‘,’ entonces agréguelas a la lista de conectores y modifique la segunda condición de todas a cualquiera

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

salida:

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

Prueba este regex

 apple.*banana|banana.*apple 

El código es:

 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')] 

Salida

  ID String_Col 2 3 apple and banana both are delicious 

Enumerar todas las posibilidades para listas grandes es engorroso. Una mejor manera es utilizar reduce() y el operador Y ( & ) a nivel de bits .

Por ejemplo, considere el siguiente DataFrame:

 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 

Supongamos que queremos buscar todo lo siguiente:

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

Podemos hacer:

 #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