2015-04-21 20 views
9

Sto provando a creare una nuova colonna che restituisce la media dei valori di una colonna esistente nello stesso df. Tuttavia, la media dovrebbe essere calcolata in base a un raggruppamento in altre tre colonne.Panda dataframe condizionale .mean() in base ai valori in alcune colonne

Out[184]: 
    YEAR daytype hourtype scenario option_value  
0 2015  SAT  of_h   0  0.134499  
1 2015  SUN  of_h   1  63.019250  
2 2015  WD  of_h   2  52.113516  
3 2015  WD  pk_h   3  43.126513  
4 2015  SAT  of_h   4  56.431392 

ho praticamente piacerebbe avere una nuova colonna 'media', che calcola la media di "valore di opzione", quando "anno", "daytype", e "hourtype" sono simili.

ho provato l'approccio seguito, ma senza successo ...

In [185]: o2['premium']=o2.groupby(['YEAR', 'daytype', 'hourtype'])['option_cf'].mean() 

TypeError: incompatible index of inserted column with frame index 
+1

Stai chiamando '['option_cf']' ma il tuo dataframe ha '['option_value']'. – ASGM

+0

Quindi, per le righe 2015-SAT-of_h, vuoi che vengano compresse in una nuova riga, o vuoi che entrambe le righe esistano ancora, ma hai una colonna "premium" con lo stesso valore medio? – DSM

+0

In effetti entrambe le righe esistono ancora ma con una colonna "premium" con lo stesso valore medio .. ma questo è quello che viene proposto di seguito! – tpapz

risposta

7

Ecco un modo per farlo

In [19]: def cust_mean(grp): 
    ....:  grp['mean'] = grp['option_value'].mean() 
    ....:  return grp 
    ....: 

In [20]: o2.groupby(['YEAR', 'daytype', 'hourtype']).apply(cust_mean) 
Out[20]: 
    YEAR daytype hourtype scenario option_value  mean 
0 2015  SAT  of_h   0  0.134499 28.282946 
1 2015  SUN  of_h   1  63.019250 63.019250 
2 2015  WD  of_h   2  52.113516 52.113516 
3 2015  WD  pk_h   3  43.126513 43.126513 
4 2015  SAT  of_h   4  56.431392 28.282946 

Allora, che cosa stava andando male con il tuo tentativo?

Restituisce un aggregato con una forma diversa rispetto al dataframe originale.

In [21]: o2.groupby(['YEAR', 'daytype', 'hourtype'])['option_value'].mean() 
Out[21]: 
YEAR daytype hourtype 
2015 SAT  of_h  28.282946 
     SUN  of_h  63.019250 
     WD  of_h  52.113516 
       pk_h  43.126513 
Name: option_value, dtype: float64 

O uso transform

In [1461]: o2['premium'] = (o2.groupby(['YEAR', 'daytype', 'hourtype'])['option_value'] 
           .transform('mean')) 

In [1462]: o2 
Out[1462]: 
    YEAR daytype hourtype scenario option_value premium 
0 2015  SAT  of_h   0  0.134499 28.282946 
1 2015  SUN  of_h   1  63.019250 63.019250 
2 2015  WD  of_h   2  52.113516 52.113516 
3 2015  WD  pk_h   3  43.126513 43.126513 
4 2015  SAT  of_h   4  56.431392 28.282946 
+1

Mille grazie, funziona bene. Una domanda però .. come mai il tuo metodo non restituisce anche un output aggregato? – tpapz

1

si può fare come si intendeva modificando il codice nel seguente modo:

o2 = o2.set_index(['YEAR', 'daytype', 'hourtype']) 

o2['premium'] = o2.groupby(level=['YEAR', 'daytype', 'hourtype'])['option_value'].mean() 

Perché l'errore originale? Come spiegato da John Galt, i dati che escono da groupby(). Mean() non hanno la stessa forma (lunghezza) del DataFrame originale.

I panda possono gestirlo in modo intelligente se si inizia con le "colonne di raggruppamento" nell'indice. Quindi sa come propagare correttamente i dati medi.

La soluzione di John segue la stessa logica, poiché groupby colloca naturalmente le colonne di raggruppamento nell'indice durante l'esecuzione.