Je travaille avec la bibliothèque pandas et je souhaite ajouter deux nouvelles colonnes à un dataframedf
avec n colonnes (n> 0).
Ces nouvelles colonnes résultent de l'application d'une fonction à l'une des colonnes du dataframe.
La fonction à appliquer est comme:
def calculate(x):
...operate...
return z, y
Une méthode pour créer une nouvelle colonne pour une fonction ne renvoyant qu'une valeur est:
df['new_col']) = df['column_A'].map(a_function)
Donc, ce que je veux, et j'ai essayé sans succès (*), c'est quelque chose comme:
(df['new_col_zetas'], df['new_col_ys']) = df['column_A'].map(calculate)
Quelle pourrait être la meilleure façon d'y parvenir? J'ai scanné le documentation sans aucune idée.
** df['column_A'].map(calculate)
renvoie une série pandas chaque élément consistant en un tuple z, y. Et essayer d'attribuer ceci à deux colonnes de dataframe produit une ValueError. *
La meilleure réponse est imparfaite à mon avis. Espérons que personne n'importe en masse tous les pandas dans leur espace de noms avec
from pandas import *
. En outre, lamap
méthode doit être réservée à ces moments lorsque vous lui passez un dictionnaire ou une série. Cela peut prendre une fonction mais c'est ce queapply
est utilisé.Donc, si vous devez utiliser l'approche ci-dessus, je l'écrirais comme ceci
Il n'y a en fait aucune raison d'utiliser zip ici. Vous pouvez simplement faire ceci:
Cette deuxième méthode est également beaucoup plus rapide sur des DataFrames plus volumineux
DataFrame créé avec 300 000 lignes
60x plus rapide que zip
En général, évitez d'utiliser apply
Apply n'est généralement pas beaucoup plus rapide que d'itérer sur une liste Python. Testons les performances d'une boucle for pour faire la même chose que ci-dessus
C'est donc deux fois plus lent, ce qui n'est pas une terrible régression des performances, mais si nous cythonisons ce qui précède, nous obtenons de bien meilleures performances. En supposant que vous utilisez ipython:
Attribuer directement sans appliquer
Vous pouvez obtenir des améliorations de vitesse encore plus importantes si vous utilisez les opérations vectorisées directes.
Cela tire parti des opérations vectorisées extrêmement rapides de NumPy au lieu de nos boucles. Nous avons maintenant une accélération 30x par rapport à l'original.
Le test de vitesse le plus simple avec
apply
L'exemple ci-dessus devrait clairement montrer à quel point il
apply
peut être lent , mais pour qu'il soit très clair, examinons l'exemple le plus basique. Mettons au carré une série de 10 millions de nombres avec et sans applicationSans appliquer est 50 fois plus rapide
la source
applymap
dans le cas où vous devez implémenter une fonction spécifique à chaque élément du dataframe?func(series)
au lieu deseries.apply(func)
n'est applicable que lorsque la fonction est entièrement définie à l'aide d'opérations qui se comportent de la même manière sur une valeur individuelle et sur une série. C'est le cas dans l'exemple de la première réponse, mais ce n'est pas le cas dans la question de l'OP, qui pose plus généralement sur l'application de fonctions aux colonnes. 1/2DataFrame({'a': ['Aaron', 'Bert', 'Christopher'], 'b': ['Bold', 'Courageous', 'Distrusted']})
etcalc
est:def calc(x): return x[0], len(x)
alorstdf.a.apply(calc))
etcalc(tdf.a)
renvoie des choses très différentes.