Pandas: Quelle est la manière la plus efficace d'itérer le DataFrame de Pandas ligne par ligne?

Créé le 12 juin 2015  ·  6Commentaires  ·  Source: pandas-dev/pandas

J'ai essayé la fonction df.iterrows() mais ses performances sont horribles. Ce qui n'est pas surprenant étant donné que iterrows() renvoie un Series avec un schéma complet et des métadonnées, pas seulement les valeurs (dont tout ce dont j'ai besoin).

La deuxième méthode que j'ai essayée est for row in df.values , ce qui est beaucoup plus rapide. Cependant, j'ai récemment réalisé que df.values n'est pas le stockage de données interne du DataFrame, car df.values convertit tout dtypes en un dtype commun. Par exemple, une de mes colonnes a dtype int64 mais le dtype de df.values est tout float64 . Je soupçonne donc que df.values crée en fait une autre copie des données internes.

En outre, une autre condition est que l'itération de ligne doit renvoyer une liste de valeurs qui préservent l'original dtype des données.

Usage Question

Commentaire le plus utile

Je pense que df.itertuples() est ce que vous recherchez - c'est beaucoup plus rapide qu'il ne le fait:

In [10]: x = pd.DataFrame({'x': range(10000)})

In [11]: %timeit list(x.iterrows())
1 loops, best of 3: 383 ms per loop

In [12]: %timeit list(x.itertuples())
1000 loops, best of 3: 1.39 ms per loop

Tous les 6 commentaires

En python, itérer sur les lignes sera (beaucoup) plus lent que de faire des opérations vectorisées.

Les types sont convertis dans votre deuxième méthode car c'est ainsi que fonctionnent les tableaux numpy (c'est ce que df.values ). Les DataFrames sont basés sur des colonnes, vous pouvez donc avoir un seul DataFrame avec plusieurs dtypes. Une fois que vous effectuez une itération par ligne, tout doit être converti en un type plus général qui contient tout. Dans votre cas, les entiers vont à float64 .

Si vous décrivez votre problème avec un exemple de travail minimal, nous pourrons peut-être vous aider à le vectoriser. Vous pouvez également avoir de la chance sur StackOverflow avec la balise pandas.

En gros, je veux faire ce qui suit:

row_handler = RowHandler(sample_df)  # learn how to handle row from sample data
transformed_data = []
for row in df.values:
    transformed_data.append(row_handler.handle(row))
return transformed_data

Je ne possède pas la classe RowHandler et je ne peux donc fonctionner que ligne par ligne.

Un autre exemple similaire est celui de l'apprentissage automatique, où vous pouvez avoir un modèle qui a une API de prédiction au niveau de la ligne uniquement.

Encore un peu trop vague pour être utile. Mais si RowHandler est vraiment hors de votre contrôle, vous n'aurez pas de chance. FWIW toutes les API de scikit-learn fonctionnent sur des tableaux (donc plusieurs lignes).

Je ne vois pas comment cela peut être plus clair. Oui, RowHandler est hors de mon contrôle. Qu'entendez-vous par malchance? Ma question est la façon la plus efficace d'itérer sur les lignes tout en gardant intact le dtype de chaque élément. Proposez-vous df.iterrows() , ou autre chose?

sklearn est une exception, pas la norme, qui opère nativement sur les DataFrame PD. Peu de bibliothèques de machine learning ont des API qui fonctionnent sur DataFrame .

Je pense que df.itertuples() est ce que vous recherchez - c'est beaucoup plus rapide qu'il ne le fait:

In [10]: x = pd.DataFrame({'x': range(10000)})

In [11]: %timeit list(x.iterrows())
1 loops, best of 3: 383 ms per loop

In [12]: %timeit list(x.itertuples())
1000 loops, best of 3: 1.39 ms per loop

Merci @shoyer! C'est ce dont j'ai besoin.

Cette page vous a été utile?
0 / 5 - 0 notes