J'ai un dataframe pandas géants, df_test
. Il contient une colonne «taille» qui représente la taille en octets. J'ai calculé Ko, Mo et Go à l'aide du code suivant:
df_test = pd.DataFrame([
{'dir': '/Users/uname1', 'size': 994933},
{'dir': '/Users/uname2', 'size': 109338711},
])
df_test['size_kb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0, grouping=True) + ' KB')
df_test['size_mb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 2, grouping=True) + ' MB')
df_test['size_gb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 3, grouping=True) + ' GB')
df_test
dir size size_kb size_mb size_gb
0 /Users/uname1 994933 971.6 KB 0.9 MB 0.0 GB
1 /Users/uname2 109338711 106,776.1 KB 104.3 MB 0.1 GB
[2 rows x 5 columns]
J'ai exécuté cela sur 120000 lignes et cela prend environ 2,97 secondes par colonne * 3 = ~ 9 secondes selon% timeit.
Est-ce que je peux faire cela plus rapidement? Par exemple, puis-je au lieu de renvoyer une colonne à la fois à partir de Apply et de l'exécuter 3 fois, puis-je retourner les trois colonnes en un seul passage pour les réinsérer dans le dataframe d'origine?
Les autres questions que j'ai trouvées veulent toutes prendre plusieurs valeurs et renvoyer une seule valeur . Je veux prendre une seule valeur et renvoyer plusieurs colonnes .
rows_list
contient cette réponse?pd.Series(data, index=...)
. Sinon, vous obtenez des erreurs cryptiques lorsque vous essayez de réattribuer le résultat dans la trame de données parent.Utilisez appliquer et zip 3 fois plus vite que la série.
Les résultats du test sont:
la source
Certaines des réponses actuelles fonctionnent bien, mais je veux proposer une autre option, peut-être plus «pandifiée». Cela fonctionne pour moi avec les pandas actuels 0.23 ( je ne sais pas si cela fonctionnera dans les versions précédentes):
Notez que l'astuce est sur le
result_type
paramètre deapply
, qui étendra son résultat en unDataFrame
qui peut être directement assigné aux nouvelles / anciennes colonnes.la source
Juste une autre manière lisible. Ce code ajoutera trois nouvelles colonnes et ses valeurs, renvoyant des séries sans paramètres d'utilisation dans la fonction apply.
Un exemple général tiré de: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.apply.html
la source
Des réponses vraiment cool! Merci Jesse et jaumebonet! Juste une observation en ce qui concerne:
zip(* ...
... result_type="expand")
Bien que expand soit plus élégant ( pandifié ), zip est au moins ** 2x plus rapide . Sur cet exemple simple ci-dessous, j'ai été 4x plus rapide .
la source
La performance entre les principales réponses est considérablement variée, et Jesse & famaral42 en ont déjà discuté, mais il vaut la peine de partager une comparaison équitable entre les principales réponses et de développer un détail subtil mais important de la réponse de Jesse: l'argument transmis au fonction, affecte également les performances .
(Python 3.7.4, Pandas 1.0.3)
Voici les résultats:
Notez que le renvoi de tuples est la méthode la plus rapide, mais ce qui est passé en argument affecte également les performances. La différence dans le code est subtile mais l'amélioration des performances est significative.
Le test n ° 4 (passage d'une seule valeur) est deux fois plus rapide que le test n ° 3 (passage en série), même si l'opération effectuée est apparemment identique.
Mais il y a plus ...
Dans certains cas (# 1a et # 4a), appliquer la fonction à un DataFrame dans lequel les colonnes de sortie existent déjà est plus rapide que de les créer à partir de la fonction.
Voici le code pour exécuter les tests:
la source
Je crois que la version 1.1 rompt le comportement suggéré dans la réponse supérieure ici.
Le code ci-dessus exécuté sur pandas 1.1.0 renvoie:
Alors que dans pandas 1.0.5, il est retourné:
Ce à quoi je pense que vous vous attendez.
Je ne sais pas comment les notes de publication expliquent ce comportement, mais comme expliqué ici, éviter la mutation des lignes d'origine en les copiant ressuscite l'ancien comportement. c'est à dire:
la source
Généralement, pour renvoyer plusieurs valeurs, c'est ce que je fais
Le retour d'un dataframe a définitivement ses avantages, mais parfois pas obligatoire. Vous pouvez regarder ce que les
apply()
retours et jouer un peu avec les fonctions;)la source
Il donne un nouveau dataframe avec deux colonnes de l'original.
la source