Ne pandas iterrows ont des problèmes de performances?
J'ai remarqué de très mauvaises performances lors de l'utilisation de iterrows de pandas.
Est-ce quelque chose qui est vécu par les autres? Est-il spécifique à iterrows et si cette fonction a éviter pour les données d'une certaine taille (je travaille avec 2 à 3 millions de lignes)?
Cette discussion sur GitHub m'a amené à croire qu'il est causé lorsque le mélange dtypes dans le dataframe, cependant l'exemple simple ci-dessous montre qu'il est là, même lors de l'utilisation d'un dtype (float64). Cela prend 36 secondes sur ma machine:
import pandas as pd
import numpy as np
import time
s1 = np.random.randn(2000000)
s2 = np.random.randn(2000000)
dfa = pd.DataFrame({'s1': s1, 's2': s2})
start = time.time()
i=0
for rowindex, row in dfa.iterrows():
i+=1
end = time.time()
print end - start
Pourquoi vectorisé opérations d'appliquer de manière beaucoup plus rapide? J'imagine qu'il doit y avoir une certaine ligne par ligne itération y passe aussi.
Je ne peux pas comprendre comment l'utilisez pas iterrows dans mon cas (ce que je vais économiser pour l'avenir d'une question). Donc j'aimerais connaître si vous avez toujours été en mesure d'éviter cette itération. Je suis en train de faire des calculs basés sur des données distinctes dataframes. Merci!!!!
---Edit: version simplifiée de ce que je veux exécuter a été ajouté en dessous de---
import pandas as pd
import numpy as np
#%% Create the original tables
t1 = {'letter':['a','b'],
'number1':[50,-10]}
t2 = {'letter':['a','a','b','b'],
'number2':[0.2,0.5,0.1,0.4]}
table1 = pd.DataFrame(t1)
table2 = pd.DataFrame(t2)
#%% Create the body of the new table
table3 = pd.DataFrame(np.nan, columns=['letter','number2'], index=[0])
#%% Iterate through filtering relevant data, optimizing, returning info
for row_index, row in table1.iterrows():
t2info = table2[table2.letter == row['letter']].reset_index()
table3.ix[row_index,] = optimize(t2info,row['number1'])
#%% Define optimization
def optimize(t2info, t1info):
calculation = []
for index, r in t2info.iterrows():
calculation.append(r['number2']*t1info)
maxrow = calculation.index(max(calculation))
return t2info.ix[maxrow]
apply
n'est PAS vectorisé.iterrows
est encore pire car elle boîtes tout (que' la diff de perf avecapply
). Vous devez uniquement utiliseriterrows
dans très très peu de situations. À mon humble avis ne jamais. Montrez ce que vous êtes en train de faire aveciterrows
.- Le problème est lié à au lieu de cela a à voir avec la boxe de
DatetimeIndex
enTimestamps
(a été mis en œuvre dans l'espace python), et cela a été beaucoup améliorée en maître. - Voir ce problème pour une discussion complète sur le sujet: github.com/pydata/pandas/issues/7194.
- Lien à la question spécifique (celui-ci restera général): stackoverflow.com/questions/24875096/...
- s'il vous Plaît ne recommande pas l'utilisation de iterrows(). C'est un flagrant enabler des pires anti-modèle dans l'histoire de pandas.
Vous devez vous connecter pour publier un commentaire.
Généralement,
iterrows
ne devraient être utilisés que dans des cas très spécifiques. C'est le général de l'ordre de priorité pour l'exécution de diverses opérations:À l'aide d'un custom cython de routine est généralement trop compliqué, donc passons pour l'instant.
1) la Vectorisation est toujours TOUJOURS le premier et le meilleur choix. Cependant, il existe un petit ensemble de cas qui ne peuvent pas être vectorisé de manière évidente (surtout impliquant une répétition). Plus loin, sur une petite image, il peut être plus rapide de faire d'autres méthodes.
3) s'Appliquent implique peut généralement être fait par un itérateur en Cython de l'espace (ce qui est fait en interne dans les pandas) (c'est un) cas.
Cela dépend de ce qui se passe à l'intérieur de l'appliquer expression. par exemple,
df.apply(lambda x: np.sum(x))
sera exécuté assez rapidement (bien sûrdf.sum(1)
est encore mieux). Cependant quelque chose comme:df.apply(lambda x: x['b'] + 1)
sera exécuté dans l'espace python, et, par conséquent, est plus lent.4)
itertuples
ne pas cocher les données dans une Série, juste renvoie sous la forme d'un tuple5)
iterrows
NE cocher les données dans une Série. À moins que vous vraiment besoin, utiliser une autre méthode.6) mise à jour d'un cadre vide un-seul-ligne-à-un-temps. J'ai vu cette méthode utilisé de FAÇON trop. C'est de loin le plus lent. C'est sans doute un lieu commun (et assez rapide pour certains python structures), mais un DataFrame fait un bon nombre de contrôles sur l'indexation, de sorte que ce sera toujours très lent à mettre à jour une ligne à la fois. Beaucoup mieux de créer de nouvelles structures et
concat
.itertuples
est plus rapide queapply
🙁pd.DataFrame.apply
est souvent plus lent queitertuples
. En outre, il est utile de considérer interprétations de la liste,map
, la mal nomméenp.vectorize
etnumba
(dans aucun ordre particulier) pour non-vectorisable calculs, voir, par exemple, cette réponse.Vecteur opérations dans Numpy et les pandas sont beaucoup plus rapide que scalaire opérations de vanille Python pour plusieurs raisons:
Amorti type de recherche: Python est un typées dynamiquement la langue, il y a gestion d'exécution de chaque élément dans un tableau. Cependant, Numpy (et donc les pandas) effectuer les calculs dans C (souvent par l'intermédiaire des Cython). Le type du tableau est déterminé au début de l'itération; cette épargne seul est l'une des plus grandes victoires.
Meilleure mise en cache: Itération sur un C tableau, le cache est accessible et donc très rapide. Une pandas DataFrame est orienté sur la colonne "table", ce qui signifie que chaque colonne est vraiment juste un tableau. Donc la native actions que vous pouvez effectuer sur un DataFrame (comme en additionnant les éléments dans une colonne) vont avoir quelques défauts de cache.
Plus de possibilités de parallélisme: Un simple C tableau peut être opéré via des instructions SIMD. Certaines parties de Numpy permettre SIMD, en fonction de votre CPU et le processus d'installation. Les avantages pour le parallélisme ne sera pas aussi spectaculaire que le typage statique et une meilleure gestion du cache, mais ils sont encore une victoire solide.
Morale de l'histoire: utiliser le vecteur des opérations dans Numpy et les pandas. Ils sont plus rapides que les scalaires opérations en Python, pour la simple raison que ces opérations sont exactement ce qu'est un programmeur C qui l'aurait écrit à la main de toute façon. (Sauf que le tableau notion est beaucoup plus facile à lire qu'explicite des boucles avec embedded instructions SIMD.)
Ici est la façon de faire de votre problème. C'est tout vectorisé.
Une autre option est d'utiliser
to_records()
, qui est plus rapide que les deuxitertuples
etiterrows
.Mais pour votre cas, il y a beaucoup de place pour d'autres types d'améliorations.
Voici ma dernière version optimisée
Test de référence:
Code complet:
La version finale est presque 10 fois plus rapide que le code d'origine. La stratégie est:
groupby
d'éviter la répétition de comparer les valeurs.to_records
pour accéder à raw numpy.les enregistrements des objets.Oui, les Pandas itertuples() est plus rapide que iterrows().
vous pouvez vous référer à la documentation: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iterrows.html
"Pour préserver dtypes lors de l'itération sur les lignes, il est préférable d'utiliser itertuples() qui retourne namedtuples des valeurs, et qui est généralement plus rapide que iterrows."