2012-08-30 18 views
8

Ho un dataframe 'RPT' indicizzato da (STK_ID, RPT_Date), contiene le vendite di stock accumulate per ogni qurter:Come fare un 'groupby' di indice multilivello in Pandas

     sales 
STK_ID RPT_Date 
000876 20060331  798627000 
     20060630  1656110000 
     20060930  2719700000 
     20061231  3573660000 
     20070331  878415000 
     20070630  2024660000 
     20070930  3352630000 
     20071231  4791770000 
600141 20060331  270912000 
     20060630  658981000 
     20060930  1010270000 
     20061231  1591500000 
     20070331  319602000 
     20070630  790670000 
     20070930  1250530000 
     20071231  1711240000 

voglio calcolare le singole vendite di qurterly usando "groupby" di STK_ID & RPT_Yr, come ad esempio: RPT.groupby('STK_ID','RPT_Yr')['sales'].transform(lambda x: x-x.shift(1)), come fare?

supporre che posso ottenere l'anno lambda x : datetime.strptime(x, '%Y%m%d').year

risposta

8

Supponendo che qui RPT_Data è una stringa, alcuna ragione per cui non usare Datetime?

È possibile raggruppare usando le funzioni, ma solo su un indice non MultiIndex. Lavorando su questo, resettando l'indice, e impostando 'RPT_Date' come indice per estrarre l'anno (nota: pandas alterna tra object e int come dtype per 'RPT_Date').

In [135]: year = lambda x : datetime.strptime(str(x), '%Y%m%d').year 

In [136]: grouped = RPT.reset_index().set_index('RPT_Date').groupby(['STK_ID', year]) 

In [137]: for key, df in grouped: 
    .....:  print key 
    .....:  print df 
    .....: 
(876, 2006) 
      STK_ID  sales 
RPT_Date 
20060331  876 798627000 
20060630  876 1656110000 
20060930  876 2719700000 
20061231  876 3573660000 
(876, 2007) 
      STK_ID  sales 
RPT_Date 
20070331  876 878415000 
20070630  876 2024660000 
20070930  876 3352630000 
20071231  876 4791770000 
(600141, 2006) 
      STK_ID  sales 
RPT_Date 
20060331 600141 270912000 
20060630 600141 658981000 
20060930 600141 1010270000 
20061231 600141 1591500000 
(600141, 2007) 
      STK_ID  sales 
RPT_Date 
20070331 600141 319602000 
20070630 600141 790670000 
20070930 600141 1250530000 
20071231 600141 1711240000 

Altra opzione è quella di utilizzare una colonna tmp

In [153]: RPT_tmp = RPT.reset_index() 

In [154]: RPT_tmp['year'] = RPT_tmp['RPT_Date'].apply(year) 

In [155]: grouped = RPT_tmp.groupby(['STK_ID', 'year']) 

EDIT Riorganizzare il telaio rendono molto più facile.

In [48]: RPT 
Out[48]: 
            sales 
STK_ID RPT_Year RPT_Quarter    
876 2006  0    798627000 
       1   1656110000 
       2   2719700000 
       3   3573660000 
     2007  0    878415000 
       1   2024660000 
       2   3352630000 
       3   4791770000 
600141 2006  0    270912000 
       1    658981000 
       2   1010270000 
       3   1591500000 
     2007  0    319602000 
       1    790670000 
       2   1250530000 
       3   1711240000 

In [49]: RPT.groupby(level=['STK_ID', 'RPT_Year'])['sales'].apply(sale_per_q) 
Out[49]: 
STK_ID RPT_Year RPT_Quarter 
876  2006  0    798627000 
        1    857483000 
        2    1063590000 
        3    853960000 
     2007  0    878415000 
        1    1146245000 
        2    1327970000 
        3    1439140000 
600141 2006  0    270912000 
        1    388069000 
        2    351289000 
        3    581230000 
     2007  0    319602000 
        1    471068000 
        2    459860000 
        3    460710000 
+2

È piuttosto complicato e il codice è brutto. C'è qualche modo pitonico o pandasnico per farlo? – bigbug

+0

qual è il codice di 'sale_per_q'? – bigbug

+0

def sale_per_q (s): sq = s.diff() sq [s.index [0]] = s.iget (0) ritorno sq –

0

Prova

RPT['sales'].groupby([RPT['STK_ID'],RPT['RPT_Yr']]).sum() 

^^ è necessario fare riferimento gli indici all'interno di un elenco. questo ha funzionato per me

Problemi correlati