2015-04-21 34 views
9

Próbuję utworzyć nową kolumnę, która zwraca średnią wartości z istniejącej kolumny w tym samym df. Jednak średnia powinna być obliczana na podstawie grupowania w trzech innych kolumnach.Panda ramka danych warunkowa .mean() w zależności od wartości w pewnej kolumnie

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 

I w zasadzie chciałoby mieć nową kolumnę „średni”, który obliczyć średnią wartość opcji „”, gdy „rok”, „daytype” i „hourtype” są podobne.

Próbowałem następujące podejście, ale bez powodzenia ...

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

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

Nazywasz '['option_cf']' ale twoja ramka danych ma '['wartość_opcji']'. – ASGM

+0

Tak więc dla wierszy 2015-SAT-of_h, czy chcesz, aby były zwinięte w jeden nowy wiersz, czy też chcesz, aby oba wiersze nadal istnieją, ale mają kolumnę "premium" z (taką samą) średnią wartością? – DSM

+0

Rzeczywiście oba wiersze nadal istnieją, ale z kolumną "premium" z tą samą średnią wartością. Ale to jest "proponowane poniżej! – tpapz

Odpowiedz

7

Oto jeden ze sposobów, aby to zrobić

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 

Więc, co się dzieje nie tak z próby?

Powoduje zwrócenie agregatu o innym kształcie niż oryginalna ramka danych.

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 

Albo użycie 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

Wielkie dzięki, ładnie działa. Jedno pytanie jednak ... dlaczego Twoja metoda nie zwraca również zagregowanego wyniku? – tpapz

1

Można zrobić to w sposób zamierzony przez szczypanie swój kod w następujący sposób:

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

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

Dlaczego oryginalne błędzie? Jak wyjaśnił John Galt, dane wychodzące z groupby(). Mean() nie mają tego samego kształtu (długości) co oryginalna DataFrame.

Pandy potrafią poradzić sobie z tym sprytnie, jeśli najpierw zaczniesz od "grupowania kolumn" w indeksie. Wtedy wie, jak prawidłowo propagować średnie dane.

Rozwiązanie Johna jest zgodne z tą samą logiką, ponieważ groupby naturalnie umieszcza kolumny grupujące w indeksie podczas wykonywania.