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.
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.
Commentaire le plus utile
Je pense que
df.itertuples()
est ce que vous recherchez - c'est beaucoup plus rapide qu'il ne le fait: