Rechercher «ne contient pas» sur un DataFrame dans les pandas

142

J'ai fait des recherches et je ne peux pas comprendre comment filtrer un dataframe par df["col"].str.contains(word), mais je me demande s'il existe un moyen de faire l'inverse: filtrer un dataframe par le compliment de cet ensemble. par exemple: à l'effet de !(df["col"].str.contains(word)).

Cela peut-il être fait par une DataFrameméthode?

stite
la source

Réponses:

264

Vous pouvez utiliser l'opérateur invert (~) (qui agit comme un pas pour les données booléennes):

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

, où new_dfest la copie retournée par RHS.

contient aussi accepte une expression régulière ...


Si ce qui précède génère une ValueError, la raison est probablement due au fait que vous avez des types de données mixtes, utilisez donc na=False:

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

Ou,

new_df = df[df["col"].str.contains(word) == False]
Andy Hayden
la source
1
Parfait! Je connais SQL avec regex et je pensais que c'était différent en Python - j'ai vu beaucoup d'articles avec re.complieset je me suis dit que j'y reviendrais plus tard. On dirait que je suradapte la recherche et c'est comme vous le dites
:)
6
Un exemple complet serait peut-être utile: df[~df.col.str.contains(word)]renvoie une copie du dataframe d'origine avec les lignes exclues correspondant au mot.
Dennis Golomazov
45

J'avais également des problèmes avec le symbole not (~), alors voici une autre façon d'un autre thread StackOverflow :

df[df["col"].str.contains('this|that')==False]
nanselm2
la source
Peut-il être combiné comme ça? df[df["col1"].str.contains('this'|'that')==False and df["col2"].str.contains('foo'|'bar')==True]? Merci!
tommy.carstensen
Oui, vous pouvez. La syntaxe est expliquée ici: stackoverflow.com/questions/22086116/…
tommy.carstensen
Ne pas oublier que si nous voulons rwmove les lignes qui contiennent "|" nous devrions utiliser "\" comme df = df[~df["col"].str.contains('\|')]
Amir
9

Vous pouvez utiliser Apply et Lambda pour sélectionner des lignes dans lesquelles une colonne contient tout élément d'une liste. Pour votre scénario:

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

J'ai dû me débarrasser des valeurs NULL avant d'utiliser la commande recommandée par Andy ci-dessus. Un exemple:

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

Maintenant, exécutez la commande:

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

J'obtiens l'erreur suivante:

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

Je me suis débarrassé des valeurs NULL en utilisant d'abord dropna () ou fillna () et j'ai réessayé la commande sans problème.

Shoresh
la source
1
Vous pouvez également utiliser ~df["second"].astype(str).str.contains(word)pour forcer la conversion en str. Voir stackoverflow.com/questions/43568760/…
David C
1
@Shoresh, nous pouvons également utiliser na = False comme solution à ce problème
Vishav Gupta
5

J'espère que les réponses sont déjà postées

J'ajoute le cadre pour trouver plusieurs mots et annuler ceux de dataFrame .

Ici 'word1','word2','word3','word4'= liste des motifs à rechercher

df = DataFrame

column_a = Un nom de colonne 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
la source
3

En plus de la réponse de nanselm2, vous pouvez utiliser à la 0place de False:

df["col"].str.contains(word)==0
U10-avant
la source
il semble que ceci supprime également toutes les lignes avecNaN
bshelt141