J'ai un DataFrame
des pandas:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Production:
c1 c2
0 10 100
1 11 110
2 12 120
Maintenant, je veux parcourir les lignes de ce cadre. Pour chaque ligne, je veux pouvoir accéder à ses éléments (valeurs dans les cellules) par le nom des colonnes. Par exemple:
for row in df.rows:
print row['c1'], row['c2']
Est-il possible de faire cela chez les pandas?
J'ai trouvé cette question similaire . Mais cela ne me donne pas la réponse dont j'ai besoin. Par exemple, il est suggéré d'y utiliser:
for date, row in df.T.iteritems():
ou
for row in df.iterrows():
Mais je ne comprends pas ce qu'est l' row
objet et comment je peux travailler avec lui.
iter*
les fonctions doivent être utilisées dans de très rares circonstances. Également lié .iterrows
, il existe de meilleures façons d'itérer sur un DataFrame, vous pourriez tout aussi bien parcourir une liste de listes à ce stade. Si vous êtes au point où vous ne faites rien d'autre que d'itérer sur des DataFrames, il n'y a vraiment aucun avantage à utiliser un DataFrame (en supposant que l'itérer dessus est la seule chose que vous faites avec). Juste mon 2c.pandas
c'est le choix de lire un fichier csv même si l'ensemble de données est petit. Il est tout simplement plus facile de programmer pour manipuler les données avec les APIRéponses:
DataFrame.iterrows est un générateur qui produit à la fois l'index et la ligne
la source
431341610650
où lire comme4.31E+11
. Existe-t-il un moyen de préserver les dtypes?itertuples
, comme expliqué ci-dessous. Voir aussi pandas.pydata.org/pandas-docs/stable/generated/…Réponse: NE PAS * !
L'itération chez les pandas est un anti-modèle, et c'est quelque chose que vous ne devriez faire que lorsque vous avez épuisé toutes les autres options. Vous ne devez utiliser aucune fonction avec "
iter
" dans son nom pendant plus de quelques milliers de lignes ou vous devrez vous habituer à beaucoup d'attente.Voulez-vous imprimer un DataFrame? Utilisation
DataFrame.to_string()
.Voulez-vous calculer quelque chose? Dans ce cas, recherchez les méthodes dans cet ordre (liste modifiée à partir d' ici ):
for
boucle vanille )DataFrame.apply()
: i) Réductions pouvant être effectuées dans le cython, ii) Itération dans l'espace pythonDataFrame.itertuples()
etiteritems()
DataFrame.iterrows()
iterrows
etitertuples
(tous deux recevant de nombreux votes dans les réponses à cette question) devraient être utilisés dans de très rares circonstances, telles que la génération d'objets de ligne / nametuples pour le traitement séquentiel, ce qui est vraiment la seule raison pour laquelle ces fonctions sont utiles.Appel à l'autorité
La page de documentation sur l'itération a une énorme boîte d'avertissement rouge qui dit:
* C'est en fait un peu plus compliqué que "pas".
df.iterrows()
est la bonne réponse à cette question, mais "vectoriser vos opérations" est la meilleure. Je concède qu'il y a des circonstances où l'itération ne peut pas être évitée (par exemple, certaines opérations où le résultat dépend de la valeur calculée pour la ligne précédente). Cependant, il faut une certaine familiarité avec la bibliothèque pour savoir quand. Si vous n'êtes pas sûr d'avoir besoin d'une solution itérative, vous n'en avez probablement pas. PS: Pour en savoir plus sur ma justification de la rédaction de cette réponse, passez au bas de la page.Plus rapide que la boucle: vectorisation , Cython
Un bon nombre d'opérations et de calculs de base sont "vectorisés" par des pandas (soit via NumPy, soit via des fonctions Cythonisées). Cela comprend l'arithmétique, les comparaisons, (la plupart) des réductions, le remodelage (comme le pivotement), les jointures et les opérations groupées. Consultez la documentation sur les fonctionnalités de base essentielles pour trouver une méthode vectorisée adaptée à votre problème.
S'il n'en existe pas, n'hésitez pas à écrire le vôtre en utilisant des extensions cython personnalisées .
Next Best Thing: List Comprehensions *
La compréhension des listes devrait être votre prochain port d'escale si 1) il n'y a pas de solution vectorisée disponible, 2) les performances sont importantes, mais pas assez importantes pour passer par les tracas de la cythonisation de votre code, et 3) vous essayez d'effectuer une transformation élémentaire sur votre code. De nombreuses preuves suggèrent que la compréhension des listes est suffisamment rapide (et même parfois plus rapide) pour de nombreuses tâches courantes de pandas.
La formule est simple,
Si vous pouvez encapsuler votre logique métier dans une fonction, vous pouvez utiliser une compréhension de liste qui l'appelle. Vous pouvez faire fonctionner des choses arbitrairement complexes grâce à la simplicité et la vitesse du python brut.
Les compréhensions de la
liste des mises en garde supposent que vos données sont faciles à utiliser - ce qui signifie que vos types de données sont cohérents et que vous n'avez pas de NaN, mais cela ne peut pas toujours être garanti.
zip(df['A'], df['B'], ...)
lieu de,df[['A', 'B']].to_numpy()
car ce dernier met implicitement à jour les données vers le type le plus courant. Par exemple, si A est numérique et B est une chaîne,to_numpy()
transtypera le tableau entier en chaîne, ce qui peut ne pas être ce que vous voulez. Heureusement,zip
cingler vos colonnes ensemble est la solution la plus simple à cela.* YMMV pour les raisons décrites dans la section Mises en garde ci-dessus.
Un exemple évident
Montrons la différence avec un exemple simple d'ajout de deux colonnes pandas
A + B
. Il s'agit d'une opération vectorisable, il sera donc facile de comparer les performances des méthodes décrites ci-dessus.Code de référence, pour votre référence.
Je dois cependant mentionner que ce n'est pas toujours aussi sec et sec. Parfois, la réponse à "quelle est la meilleure méthode pour une opération" est "cela dépend de vos données". Mon conseil est de tester différentes approches sur vos données avant d'en choisir une.
Lectures complémentaires
10 minutes pour les pandas et fonctionnalités de base essentielles - Liens utiles qui vous présentent les pandas et sa bibliothèque de fonctions vectorisées * / cythonisées.
Amélioration des performances - Une introduction de la documentation sur l'amélioration des opérations standard des pandas
Les boucles pour les pandas sont-elles vraiment mauvaises? Quand dois-je m'en soucier? - une rédaction détaillée par mes soins de la compréhension des listes et de leur adéquation à diverses opérations (principalement celles impliquant des données non numériques)
Quand devrais-je jamais vouloir utiliser pandas apply () dans mon code? -
apply
est lent (mais pas aussi lent que laiter*
famille. Il existe cependant des situations où l'on peut (ou devrait) considérerapply
comme une alternative sérieuse, notamment dans certainesGroupBy
opérations).* Les méthodes de chaîne Pandas sont "vectorisées" dans le sens où elles sont spécifiées sur la série mais fonctionnent sur chaque élément. Les mécanismes sous-jacents sont toujours itératifs, car les opérations de chaîne sont intrinsèquement difficiles à vectoriser.
Pourquoi j'ai écrit cette réponse
Une tendance courante que je remarque de nouveaux utilisateurs est de poser des questions du formulaire "comment puis-je répéter sur mon df pour faire X?". Affichage du code qui appelle
iterrows()
tout en faisant quelque chose dans une boucle for. Voici pourquoi. Un nouvel utilisateur de la bibliothèque qui n'a pas été initié au concept de vectorisation envisagera probablement le code qui résout son problème comme itérant sur ses données pour faire quelque chose. Ne sachant pas comment itérer sur un DataFrame, la première chose qu'ils font, c'est Google et finir ici, à cette question. Ils voient ensuite la réponse acceptée leur dire comment faire, et ils ferment les yeux et exécutent ce code sans jamais se demander si l'itération n'est pas la bonne chose à faire.Le but de cette réponse est d'aider les nouveaux utilisateurs à comprendre que l'itération n'est pas nécessairement la solution à chaque problème, et que des solutions meilleures, plus rapides et plus idiomatiques pourraient exister, et qu'il vaut la peine d'investir du temps pour les explorer. Je n'essaie pas de lancer une guerre d'itération contre la vectorisation, mais je veux que les nouveaux utilisateurs soient informés lors du développement de solutions à leurs problèmes avec cette bibliothèque.
la source
zip(df['A'], df['B'])
lieu dedf.iterrows()
.iterrows()
, et de dénoncer implicitement l'itération si et quand de meilleures alternatives existent.for
les boucles en elles-mêmes sont OK, mais les compréhensions de liste sont meilleures si vous effectuez de manière itérative des transformations élément par élément.DataFrame.values
convertira chaque colonne en un type de données commun.DataFrame.to_numpy()
fait cela aussi. Heureusement, nous pouvons utiliserzip
avec n'importe quel nombre de colonnes.Vérifiez d' abord si vous avez vraiment besoin d' itérer sur les lignes d'un DataFrame. Voir cette réponse pour des alternatives.
Si vous devez toujours parcourir les lignes, vous pouvez utiliser les méthodes ci-dessous. Notez quelques mises en garde importantes qui ne sont mentionnées dans aucune des autres réponses.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
est censé être plus rapide queiterrows()
Mais attention, selon la documentation (pandas 0.24.2 en ce moment):
iterrows:
dtype
peut ne pas correspondre d'une ligne à l'autreiterrows: ne modifiez pas les lignes
Utilisez plutôt DataFrame.apply () :
itertuples:
Voir les documents de pandas sur l'itération pour plus de détails.
la source
for row in df[['c1','c2']].itertuples(index=True, name=None):
inclure uniquement certaines colonnes dans l'itérateur de ligne.getattr(row, "c1")
, vous pouvez utiliser justerow.c1
.getattr(row, "c1")
place derow.c1
, vous perdez tout avantage de performanceitertuples
et si vous avez réellement besoin d'accéder à la propriété via une chaîne, vous devez utiliser iterrows à la place.numba
etcython
(les mêmes documents disent que "ça vaut toujours la peine d'être optimisé en Python d'abord"). J'ai écrit cette réponse pour aider les autres à éviter les problèmes (parfois frustrants) car aucune des autres réponses ne mentionne ces mises en garde. Tromper quelqu'un ou dire "c'est la bonne chose à faire" n'a jamais été mon intention. J'ai amélioré la réponse.Vous devez utiliser
df.iterrows()
. Bien que l'itération ligne par ligne ne soit pas particulièrement efficace car lesSeries
objets doivent être créés.la source
Bien que ce
iterrows()
soit une bonne option, celaitertuples()
peut parfois être beaucoup plus rapide:la source
for a,b,c in izip(df["a"],df["b"],df["c"]:
est presque aussi rapide.iterrows()
chaque ligne de données dans une série, alorsitertuples()
que non.df
est créé à partir d'un dictionnaire, doncrow[1]
pourrait faire référence à l'une des colonnes. Il s'avère que les temps sont à peu près les mêmes pour l'entier contre les colonnes flottantes.Vous pouvez également utiliser
df.apply()
pour parcourir les lignes et accéder à plusieurs colonnes pour une fonction.documents: DataFrame.apply ()
la source
apply
cela n'itératite pas sur les lignes, mais plutôt qu'il applique une fonction ligne par ligne. Le code ci - dessus ne fonctionnerait pas si vous vraiment faire , par exemple itérations de besoin et indeces lorsque l'on compare les valeurs entre les différentes lignes (dans ce cas , vous ne pouvez rien mais itérer).Vous pouvez utiliser la fonction df.iloc comme suit:
la source
itertuples
préserve les types de données, mais supprime tout nom qu'il n'aime pas.iterrows
fait le contraire.for i in range(df.shape[0])
puisse accélérer un peu cette approche, elle est toujours environ 3,5 fois plus lente que l'approche iterrows () ci-dessus pour mon application.my_iter = df.itertuples()
prend le double de la mémoire et beaucoup de temps pour le copier. pareil pouriterrows()
.Je cherchais comment itérer sur les lignes ET les colonnes et je me suis arrêté ici donc:
la source
Vous pouvez écrire votre propre itérateur qui implémente
namedtuple
Ceci est directement comparable à
pd.DataFrame.itertuples
. Je vise à effectuer la même tâche avec plus d'efficacité.Pour le dataframe donné avec ma fonction:
Ou avec
pd.DataFrame.itertuples
:Un test complet
Nous testons la mise à disposition de toutes les colonnes et le sous-ensemble des colonnes.
la source
intertuples
, la ligne orange est une liste d'un itérateur à travers un bloc de rendement.interrows
n'est pas comparé.Comment itérer efficacement?
Si vous devez vraiment itérer une trame de données pandas, vous voudrez probablement éviter d'utiliser iterrows () . Il existe différentes méthodes et l'habituel
iterrows()
est loin d'être le meilleur. itertuples () peut être 100 fois plus rapide.En bref:
df.itertuples(name=None)
. En particulier, lorsque vous avez un nombre fixe de colonnes et moins de 255 colonnes.Voir point (3)df.itertuples()
sauf si vos colonnes ont des caractères spéciaux tels que des espaces ou '-'.Voir point (2)itertuples()
même si votre dataframe a des colonnes étranges en utilisant le dernier exemple.Voir point (4)iterrows()
si vous ne pouvez pas utiliser les solutions précédentes. Voir point (1)Différentes méthodes pour parcourir les lignes d'une trame de données pandas:
Générez une trame de données aléatoire avec un million de lignes et 4 colonnes:
1) L'habitude
iterrows()
est pratique mais sacrément lente:2) La valeur par défaut
itertuples()
est déjà beaucoup plus rapide, mais elle ne fonctionne pas avec les noms de colonnes tels queMy Col-Name is very Strange
(vous devez éviter cette méthode si vos colonnes sont répétées ou si un nom de colonne ne peut pas être simplement converti en nom de variable python).3) La valeur
itertuples()
par défaut en utilisant name = None est encore plus rapide mais pas vraiment pratique car vous devez définir une variable par colonne.4) Enfin, le nommé
itertuples()
est plus lent que le point précédent mais vous n'avez pas à définir de variable par colonne et cela fonctionne avec des noms de colonnes tels queMy Col-Name is very Strange
.Production:
Cet article est une comparaison très intéressante entre les iterrows et les itertuples
la source
Pour boucler toutes les lignes d'un,
dataframe
vous pouvez utiliser:la source
la source
Parfois, un modèle utile est:
Ce qui se traduit par:
la source
Pour boucler toutes les lignes de a
dataframe
et utiliser les valeurs de chaque ligne de manière pratique ,namedtuples
peut être converti enndarray
s. Par exemple:Itération sur les rangées:
résulte en:
Veuillez noter que si
index=True
, l'index est ajouté en tant que premier élément du tuple , ce qui peut être indésirable pour certaines applications.la source
Il existe un moyen d'itérer les lignes de lancement tout en obtenant un DataFrame en retour, et non une série. Je ne vois personne mentionner que vous pouvez passer l'index en tant que liste pour la ligne à renvoyer en tant que DataFrame:
Notez l'utilisation de crochets doubles. Cela renvoie un DataFrame avec une seule ligne.
la source
Pour afficher et modifier des valeurs, j'utiliserais
iterrows()
. Dans une boucle for et en utilisant le décompactage de tuple (voir l'exemple:)i, row
, j'utilise lerow
pour afficher uniquement la valeur et utiliseri
avec laloc
méthode lorsque je souhaite modifier des valeurs. Comme indiqué dans les réponses précédentes, ici, vous ne devez pas modifier quelque chose que vous répétez.Ici, le
row
dans la boucle est une copie de cette ligne, et non une vue de celle-ci. Par conséquent, vous ne devez PAS écrire quelque chose commerow['A'] = 'New_Value'
cela, cela ne modifiera pas le DataFrame. Cependant, vous pouvez utiliseri
etloc
spécifier le DataFrame pour effectuer le travail.la source
Je sais que je suis en retard à la partie répondante, mais je voulais juste ajouter à la réponse de @ cs95 ci-dessus, qui je pense devrait être la réponse acceptée. Dans sa réponse, il montre que la vectorisation des pandas surpasse de loin les autres méthodes des pandas pour calculer des choses avec des trames de données.
Je voulais ajouter que si vous convertissez d'abord la trame de données en un tableau numpy puis utilisez la vectorisation, c'est encore plus rapide que la vectorisation des trames de données pandas (et cela inclut le temps de le reconvertir en une série de trames de données).
Si vous ajoutez les fonctions suivantes au code de référence de @ cs95, cela devient assez évident:
la source
Vous pouvez également effectuer une
numpy
indexation pour des accélérations encore plus importantes. Ce n'est pas vraiment une itération, mais cela fonctionne beaucoup mieux que l'itération pour certaines applications.Vous pouvez également le caster dans un tableau. Ces index / sélections sont censés agir déjà comme des tableaux Numpy mais j'ai rencontré des problèmes et je devais lancer
la source
Il y a tellement de façons de parcourir les lignes dans la trame de données des pandas. Une manière très simple et intuitive est:
la source
Cet exemple utilise iloc pour isoler chaque chiffre de la trame de données.
la source
Certaines bibliothèques (par exemple une bibliothèque Java Interop que j'utilise) nécessitent que les valeurs soient transmises dans une rangée à la fois, par exemple, en cas de streaming de données. Pour reproduire la nature du streaming, je 'stream' mes valeurs de trame de données une par une, j'ai écrit ci-dessous, ce qui est pratique de temps en temps.
Qui peut être utilisé:
Et préserve le mappage des valeurs / noms pour les lignes à itérer. Évidemment, c'est beaucoup plus lent que d'utiliser apply et Cython comme indiqué ci-dessus, mais c'est nécessaire dans certaines circonstances.
la source
En bref
Détails dans cette vidéo
Référence
la source