Je recherche un moyen efficace de supprimer les parties indésirables des chaînes d'une colonne DataFrame.
Les données ressemblent à:
time result
1 09:00 +52A
2 10:00 +62B
3 11:00 +44a
4 12:00 +30b
5 13:00 -110a
J'ai besoin de couper ces données pour:
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
J'ai essayé .str.lstrip('+-')
et. str.rstrip('aAbBcC')
, mais a obtenu une erreur:
TypeError: wrapper() takes exactly 1 argument (2 given)
Tous les pointeurs seraient grandement appréciés!
6 ans après la publication de la question initiale, les pandas ont maintenant un bon nombre de fonctions de chaîne "vectorisées" qui peuvent exécuter succinctement ces opérations de manipulation de chaînes.
Cette réponse explorera certaines de ces fonctions de chaîne, suggérera des alternatives plus rapides et passera à une comparaison des temps à la fin.
.str.replace
Spécifiez la sous-chaîne / modèle à faire correspondre et la sous-chaîne par laquelle le remplacer.
Si vous avez besoin que le résultat soit converti en entier, vous pouvez utiliser
Series.astype
,Si vous ne souhaitez pas modifier
df
sur place, utilisezDataFrame.assign
:.str.extract
Utile pour extraire la ou les sous-chaînes que vous souhaitez conserver.
Avec
extract
, il est nécessaire de spécifier au moins un groupe de capture.expand=False
renverra une série avec les éléments capturés du premier groupe de capture..str.split
et.str.get
Le fractionnement fonctionne en supposant que toutes vos chaînes suivent cette structure cohérente.
Ne pas recommander si vous recherchez une solution générale.
Optimisation: compréhension de listes
Dans certaines circonstances, les compréhensions de liste devraient être privilégiées par rapport aux fonctions de chaîne de pandas. La raison en est que les fonctions de chaîne sont intrinsèquement difficiles à vectoriser (dans le vrai sens du terme), de sorte que la plupart des fonctions de chaîne et de regex ne sont que des enveloppes autour des boucles avec plus de surcharge.
Mon article, les boucles for dans les pandas sont-elles vraiment mauvaises? Quand devrais-je m'en soucier? , entre plus en détail.
L'
str.replace
option peut être réécrite en utilisantre.sub
L'
str.extract
exemple peut être réécrit en utilisant une compréhension de liste avecre.search
,Si des NaN ou des non-correspondances sont une possibilité, vous devrez réécrire ce qui précède pour inclure une vérification des erreurs. Je fais cela en utilisant une fonction.
Nous pouvons également réécrire les réponses de @ eumiro et @ MonkeyButter en utilisant des compréhensions de liste:
Et,
Les mêmes règles pour la gestion des NaN, etc. s'appliquent.
Comparaison des performances
Graphiques générés à l'aide de perfplot . Liste complète des codes, pour votre référence. Les fonctions pertinentes sont répertoriées ci-dessous.
Certaines de ces comparaisons sont injustes car elles tirent parti de la structure des données d'OP, mais en tirent ce que vous voulez. Une chose à noter est que chaque fonction de compréhension de liste est soit plus rapide, soit comparable à sa variante pandas équivalente.
Les fonctions
la source
Try using .loc[row_indexer,col_indexer] = value instead
J'utiliserais la fonction de remplacement de pandas, très simple et puissante car vous pouvez utiliser regex. Ci-dessous, j'utilise le regex \ D pour supprimer tous les caractères non numériques, mais vous pouvez évidemment être assez créatif avec regex.
la source
df.loc[:, 'column_a'].replace(regex=True, to_replace="my_prefix", value="new_prefix")
. Cela convertira une chaîne comme "my_prefixaaa" en "new_prefixaaa".Dans le cas particulier où vous connaissez le nombre de positions que vous souhaitez supprimer de la colonne dataframe, vous pouvez utiliser l'indexation de chaîne dans une fonction lambda pour vous débarrasser de ces parties:
Dernier caractère:
Deux premiers caractères:
la source
Il y a un bug ici: actuellement impossible de passer des arguments à
str.lstrip
etstr.rstrip
:http://github.com/pydata/pandas/issues/2411
EDIT: 2012-12-07 cela fonctionne maintenant sur la branche dev:
la source
Une méthode très simple consisterait à utiliser la
extract
méthode pour sélectionner tous les chiffres. Fournissez-lui simplement l'expression régulière'\d+'
qui extrait n'importe quel nombre de chiffres.la source
J'utilise souvent des listes de compréhension pour ces types de tâches car elles sont souvent plus rapides.
Il peut y avoir de grandes différences de performances entre les différentes méthodes pour faire des choses comme celle-ci (c'est-à-dire modifier chaque élément d'une série dans un DataFrame). Souvent, la compréhension d'une liste peut être la plus rapide - voir la course au code ci-dessous pour cette tâche:
la source
Supposons que votre DF ait également ces caractères supplémentaires entre les nombres. La dernière entrée.
Vous pouvez essayer str.replace pour supprimer des caractères non seulement du début et de la fin, mais également entre les deux.
Production:
la source
Essayez ceci en utilisant une expression régulière:
la source