J'ai un pandas DataFrame et je veux en supprimer des lignes où la longueur de la chaîne dans une colonne particulière est supérieure à 2.
Je m'attends à pouvoir le faire (par cette réponse ):
df[(len(df['column name']) < 2)]
mais je reçois juste l'erreur:
KeyError: u'no item named False'
Qu'est-ce que je fais mal?
(Remarque: je sais que je peux utiliser df.dropna()
pour supprimer les lignes qui en contiennent NaN
, mais je n'ai pas vu comment supprimer les lignes basées sur une expression conditionnelle.)
df[[(len(x) < 2) for x in df['column name']]]
mais la vôtre est beaucoup plus agréable. Merci de votre aide!df[df['column name'].map(lambda x: str(x)!=".")]
pandas 0.23.4
Python 3.6.copy()
à la fin, au cas où vous souhaiteriez éditer ultérieurement ce cadre de données (par exemple, l'attribution de nouvelles colonnes déclencherait l'avertissement "Une valeur tente d'être définie sur une copie d'une tranche à partir d'un DataFrame".Pour répondre directement au titre original de cette question "Comment supprimer des lignes d'un DataFrame pandas basé sur une expression conditionnelle" (ce qui, je comprends, n'est pas nécessairement le problème de l'OP mais pourrait aider d'autres utilisateurs à rencontrer cette question) une façon de le faire est d'utiliser la méthode drop :
df = df.drop(some labels)
df = df.drop(df[<some boolean condition>].index)
Exemple
Pour supprimer toutes les lignes où la colonne «score» est <50:
df = df.drop(df[df.score < 50].index)
Version en place (comme indiqué dans les commentaires)
df.drop(df[df.score < 50].index, inplace=True)
Conditions multiples
(voir Indexation booléenne )
Pour supprimer toutes les lignes où le «score» de la colonne est <50 et> 20
df = df.drop(df[(df.score < 50) & (df.score > 20)].index)
la source
reset_index()
). J'ai trouvé cela difficile quand beaucoup de lignes ont été supprimées de mon dataframe.test = df.drop(df[df['col1'].dtype == str].index)
mais j'obtiens l'erreurKeyError: False
J'ai aussi essayédf.drop(df[df.col1.dtype == str].index)
etdf.drop(df[type(df.cleaned_norm_email) == str].index)
mais rien ne semble fonctionner? Quelqu'un peut-il me conseiller? Merci! @Userdf[(df.score < 50) & (df.score > 20)]
dans le cadre de votre réponse. Si vous inversiez cela,df = df[(df.score >= 50) | (df.score <= 20)]
vous obtiendrez votre réponse beaucoup plus rapidement.Vous pouvez affecter le
DataFrame
à une version filtrée de lui-même:C'est plus rapide que
drop
:la source
Je développerai la solution générique de @ User pour fournir un
drop
alternative gratuite. Ceci est pour les personnes dirigées ici en fonction du titre de la question (pas le problème d'OP)Supposons que vous souhaitiez supprimer toutes les lignes contenant des valeurs négatives. Une solution de revêtement est: -
Explication étape par étape: -
Générons une trame de données de distribution normale aléatoire 5x5
Que la condition supprime les négatifs. Un booléen df satisfaisant la condition: -
Une série booléenne pour toutes les lignes remplissant la condition Remarque si un élément de la ligne échoue, la ligne est marquée comme fausse
Enfin, filtrez les lignes du bloc de données en fonction de la condition
Vous pouvez attribuer revenir à df de réellement supprimer vs filtre ing fait ci - dessus
df = df[(df > 0).all(axis=1)]
Cela peut facilement être étendu pour filtrer les lignes contenant des NaN (entrées non numériques): -
df = df[(~df.isnull()).all(axis=1)]
Cela peut également être simplifié pour des cas comme: Supprimer toutes les lignes où la colonne E est négative
Je voudrais terminer avec quelques statistiques de profilage expliquant pourquoi la
drop
solution @ User est plus lente que la filtration basée sur des colonnes brutes: -Une colonne est essentiellement un à-
Series
dire unNumPy
tableau, il peut être indexé sans frais. Pour les personnes intéressées par la façon dont l'organisation de la mémoire sous-jacente joue dans la vitesse d'exécution, voici un excellent lien sur l'accélération des pandas :la source
Dans les pandas, vous pouvez faire
str.len
avec votre frontière et utiliser le résultat booléen pour la filtrer.la source
Si vous souhaitez supprimer des lignes de trame de données sur la base d'une condition compliquée sur la valeur de la colonne, l'écriture de la manière indiquée ci-dessus peut être compliquée. J'ai la solution plus simple suivante qui fonctionne toujours. Supposons que vous souhaitiez supprimer la colonne avec «en-tête», alors commencez par la répertorier.
maintenant, appliquez une fonction sur chaque élément de la liste et mettez-la dans une série panda:
dans mon cas, j'essayais juste d'obtenir le nombre de jetons:
ajoutez maintenant une colonne supplémentaire avec la série ci-dessus dans le bloc de données:
maintenant, nous pouvons appliquer des conditions sur la nouvelle colonne telles que:
la source