Buscar "no contiene" en un DataFrame en pandas

142

He realizado algunas búsquedas y no puedo encontrar la manera de filtrar un marco de datos df["col"].str.contains(word), sin embargo, me pregunto si hay una manera de hacer lo contrario: filtrar un marco de datos por el cumplido de ese conjunto. por ejemplo: a los efectos de !(df["col"].str.contains(word)).

¿Se puede hacer esto a través de un DataFramemétodo?

stites
fuente

Respuestas:

264

Puede usar el operador invertido (~) (que actúa como un no para datos booleanos):

new_df = df[~df["col"].str.contains(word)]

, donde new_dfestá la copia devuelta por RHS.

contiene también acepta una expresión regular ...


Si lo anterior arroja un ValueError, la razón es probable porque tenga tipos de datos mixtos, así que use na=False:

new_df = df[~df["col"].str.contains(word, na=False)]

O,

new_df = df[df["col"].str.contains(word) == False]
Andy Hayden
fuente
1
¡Perfecto! Estoy familiarizado con SQL con la expresión regular y pensé que era diferente en Python; vi muchos artículos re.compliesy me dije que llegaría a eso más tarde. Parece que sobreajusto la búsqueda y es justo como tú dices
:)
66
Tal vez sería útil un ejemplo completo: df[~df.col.str.contains(word)]devuelve una copia del marco de datos original con filas excluidas que coinciden con la palabra.
Dennis Golomazov
45

Estaba teniendo problemas con el símbolo no (~) también, así que aquí hay otra forma de otro hilo de StackOverflow :

df[df["col"].str.contains('this|that')==False]
nanselm2
fuente
¿Se puede combinar así? df[df["col1"].str.contains('this'|'that')==False and df["col2"].str.contains('foo'|'bar')==True]? ¡Gracias!
tommy.carstensen
Sí tu puedes. La sintaxis se explica aquí: stackoverflow.com/questions/22086116/…
tommy.carstensen
Sin olvidar que si queremos mover filas que contengan "|" deberíamos usar "\" como df = df[~df["col"].str.contains('\|')]
Amir
9

Puede usar Apply y Lambda para seleccionar filas donde una columna contiene cualquier cosa en una lista. Para su escenario:

df[df["col"].apply(lambda x:x not in [word1,word2,word3])]
Arash
fuente
6

Tuve que deshacerme de los valores NULL antes de usar el comando recomendado por Andy anteriormente. Un ejemplo:

df = pd.DataFrame(index = [0, 1, 2], columns=['first', 'second', 'third'])
df.ix[:, 'first'] = 'myword'
df.ix[0, 'second'] = 'myword'
df.ix[2, 'second'] = 'myword'
df.ix[1, 'third'] = 'myword'
df

    first   second  third
0   myword  myword   NaN
1   myword  NaN      myword 
2   myword  myword   NaN

Ahora ejecuta el comando:

~df["second"].str.contains(word)

Obtuve el siguiente error:

TypeError: bad operand type for unary ~: 'float'

Primero me deshice de los valores NULL usando dropna () o fillna () y volví a intentar el comando sin ningún problema.

Shoresh
fuente
1
También puede usar ~df["second"].astype(str).str.contains(word)para forzar la conversión a str. Ver stackoverflow.com/questions/43568760/…
David C
1
@Shoresh también podemos usar na = False como solución a este problema
Vishav Gupta
5

Espero que las respuestas ya estén publicadas

Estoy agregando el marco para encontrar varias palabras y negar las del marco de datos .

Aquí 'word1','word2','word3','word4'= lista de patrones para buscar

df = DataFrame

column_a = Un nombre de columna de DataFrame df

Search_for_These_values = ['word1','word2','word3','word4'] 

pattern = '|'.join(Search_for_These_values)

result = df.loc[~(df['column_a'].str.contains(pattern, case=False)]
Nursnaaz
fuente
3

Adicional a la respuesta de nanselm2, puede usar en 0lugar de False:

df["col"].str.contains(word)==0
U10-Adelante
fuente
parece que esto también elimina cualquier fila conNaN
bshelt141