2017-10-18 4 views
1

Je suis en train de le faire de manière intelligente plusieurs de calcul en utilisant .groupby avec pandasdataframe, avec les données suivantes:faire plusieurs opérations dans une trame de données à la fois

import numpy as np 
import pandas as pd 

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 
           'foo', 'bar', 'foo', 'foo'], 
         'B' : ['one', 'one', 'two', 'three', 
           'two', 'two', 'one', 'three'], 
         'C' : np.random.randn(8), 
         'D' : np.random.randn(8)}) 
In [2]: df 
Out[2]: 
    A  B   C   D 
0 foo one 0.469112 -0.861849 
1 bar one -0.282863 -2.104569 
2 foo two -1.509059 -0.494929 
3 bar three -1.135632 1.071804 
4 foo two 1.212112 0.721555 
5 bar two -0.173215 -0.706771 
6 foo one 0.119209 -1.039575 
7 foo three -1.044236 0.271860 

je voudrais calculer dans le plus court et façon plus rapide la suivante sortie:

A B   var1  var2  var3 
bar one  0.000000 0.000000 0.000000 
    three 0.000000 0.000000 0.000000 
    two  0.000000 0.000000 0.000000 
foo one  0.822999 19.705290 0.731207 
    three 0.000000 0.000000 0.000000 
    two  0.229541 5.509553 0.697971 

pour le moment, je sais comment le faire de manière séparée:

# lambda functions to apply 
diff = lambda x: max(x)-min(x) 
per = lambda x: (max(x)-min(x))/max(x) 
ratio1 = lambda x: (max(x)-min(x))/ len(x) 

# grouping using col C 
df.groupby(['A','B'])['C'].apply(diff) # var1 

#Grouping using col D 
df.groupby(['A','B'])['D'].apply(per) # var2 
df.groupby(['A','B'])['D'].apply(ratio1) #var3 

Editer: Je sais comment joindre tous les résultats dans une base de données mais je me demande comment faire ces 3 opérations en une seule fois. Tout conseil est accepté même de ne pas faire tout en un à cause de manque de performance ...

Répondre

2

Vous pouvez utiliser agg():

df.groupby(['A','B']).agg({'C': diff, 'D': [per, ratio1]}) 

Pour sauter la partie de changement de nom, vous pouvez appeler vos fonctions var1, var2 et var3 et l'utiliser dans groupby.

var1 = lambda x: max(x)-min(x) 
var2 = lambda x: (max(x)-min(x))/max(x) 
var3 = lambda x: (max(x)-min(x))/ len(x) 
df.groupby(['A','B']).agg({'C': var1, 'D': [var2, var3]}) 
df.columns = df.columns.droplevel() 

EDIT

Essayez avec:

def var1(x): return max(x)-min(x) 
def var2(x): return (max(x)-min(x))/max(x) 
def var3(x): return (max(x)-min(x))/ len(x) 

EDIT EDIT

Cela fonctionne pour moi sur la version pandas0.19.2:

import numpy as np 
import pandas as pd 

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 
           'foo', 'bar', 'foo', 'foo'], 
         'B' : ['one', 'one', 'two', 'three', 
           'two', 'two', 'one', 'three'], 
         'C' : np.random.randn(8), 
         'D' : np.random.randn(8)}) 

def var1(x): return max(x)-min(x) 
def var2(x): return (max(x)-min(x))/max(x) 
def var3(x): return (max(x)-min(x))/ len(x) 

df = df.groupby(['A','B']).agg({'C': var1, 'D': [var2, var3]}) 

df.columns = df.columns.droplevel() 
+0

@zipa. Ne fonctionne pas. Erreur: Les noms de fonction doivent être uniques, trouvés multiples nommés PeCaDe

+0

D'accord, changez 'lambda's en fonctions classiques :) – zipa

+0

Pour info c'est un [problème connu] (https://github.com/pandas-dev/pandas/issues/7186) – zipa