2014-07-08 10 views
7

ho un dataframe che è simile al seguente:come unstack (o ruotare?) In panda

import pandas as pd 
datelisttemp = pd.date_range('1/1/2014', periods=3, freq='D') 
s = list(datelisttemp)*3 
s.sort() 
df = pd.DataFrame({'BORDER':['GERMANY','FRANCE','ITALY','GERMANY','FRANCE','ITALY','GERMANY','FRANCE','ITALY' ], 'HOUR1':[2 ,2 ,2 ,4 ,4 ,4 ,6 ,6, 6],'HOUR2':[3 ,3 ,3, 5 ,5 ,5, 7, 7, 7], 'HOUR3':[8 ,8 ,8, 12 ,12 ,12, 99, 99, 99]}, index=s) 

Questo mi dà:

Out[458]: df 

      BORDER HOUR1 HOUR2 HOUR3 
2014-01-01 GERMANY  2  3  8 
2014-01-01 FRANCE  2  3  8 
2014-01-01 ITALY  2  3  8 
2014-01-02 GERMANY  4  5  12 
2014-01-02 FRANCE  4  5  12 
2014-01-02 ITALY  4  5  12 
2014-01-03 GERMANY  6  7  99 
2014-01-03 FRANCE  6  7  99 
2014-01-03 ITALY  6  7  99 

Voglio che il dataframe finale a guardare qualcosa di simile :

   HOUR GERMANY FRANCE ITALY 
2014-01-01 1  2  2  2  
2014-01-01 2  3  3  3 
2014-01-01 3  8  8  8 
2014-01-02 1  4  4  4 
2014-01-02 2  5  5  5 
2014-01-02 3 12  12  12 
2014-01-03 1  6  6  6 
2014-01-03 2  7  7  7 
2014-01-03 3 99  99  99 

ho fatto il seguente ma io non sono del tutto lì:

01.235.
df['date_col'] = df.index 

df2 = melt(df, id_vars=['date_col','BORDER']) 
#Can I keep the same index after melt or do I have to set an index like below? 
df2.set_index(['date_col', 'variable'], inplace=True, drop=True) 
df2 = df2.sort() 

df

Out[465]: df2 

         BORDER value 
date_col variable     
2014-01-01 HOUR1   GERMANY 2 
      HOUR1   FRANCE 2 
      HOUR1   ITALY  2 
      HOUR2   GERMANY 3 
      HOUR2   FRANCE 3 
      HOUR2   ITALY  3 
      HOUR3   GERMANY 8 
      HOUR3   FRANCE 8 
      HOUR3   ITALY  8 
2014-01-02 HOUR1   GERMANY 4 
      HOUR1   FRANCE 4 
      HOUR1   ITALY  4 
      HOUR2   GERMANY 5 
      HOUR2   FRANCE 5 
      HOUR2   ITALY  5 
      HOUR3   GERMANY 12 
      HOUR3   FRANCE 12 
      HOUR3   ITALY 12 
2014-01-03 HOUR1   GERMANY 6 
      HOUR1   FRANCE 6 
      HOUR1   ITALY  6 
      HOUR2   GERMANY 7 
      HOUR2   FRANCE 7 
      HOUR2   ITALY  7 
      HOUR3   GERMANY 99 
      HOUR3   FRANCE 99 
      HOUR3   ITALY 99 

ho pensato che avrei potuto unstack DF2 per ottenere qualcosa che assomiglia a mio dataframe finale, ma ho tutti i tipi di errori. Ho anche provato a ruotare questo dataframe ma non riesco a ottenere ciò che voglio.

risposta

13

Vogliamo valori (ad esempio 'GERMANY') per diventare nomi di colonne e nomi di colonne (ad esempio 'HOUR1') per diventare valori: uno scambio di ordinamenti.

Procedimento stack trasforma nomi di colonna in valori di indice, e il metodo il unstack trasforma valori dell'indice in nomi di colonna.

Quindi spostando i valori nell'indice, è possibile utilizzare stack e unstack per eseguire lo scambio.

import pandas as pd 

datelisttemp = pd.date_range('1/1/2014', periods=3, freq='D') 
s = list(datelisttemp)*3 
s.sort() 
df = pd.DataFrame({'BORDER':['GERMANY','FRANCE','ITALY','GERMANY','FRANCE','ITALY','GERMANY','FRANCE','ITALY' ], 'HOUR1':[2 ,2 ,2 ,4 ,4 ,4 ,6 ,6, 6],'HOUR2':[3 ,3 ,3, 5 ,5 ,5, 7, 7, 7], 'HOUR3':[8 ,8 ,8, 12 ,12 ,12, 99, 99, 99]}, index=s) 

df = df.set_index(['BORDER'], append=True) 
df.columns.name = 'HOUR' 
df = df.unstack('BORDER') 
df = df.stack('HOUR') 
df = df.reset_index('HOUR') 
df['HOUR'] = df['HOUR'].str.replace('HOUR', '').astype('int') 
print(df) 

cede

BORDER  HOUR FRANCE GERMANY ITALY 
2014-01-01  1  2  2  2 
2014-01-01  2  3  3  3 
2014-01-01  3  8  8  8 
2014-01-02  1  4  4  4 
2014-01-02  2  5  5  5 
2014-01-02  3  12  12  12 
2014-01-03  1  6  6  6 
2014-01-03  2  7  7  7 
2014-01-03  3  99  99  99 
+0

grazie per la spiegazione dettagliata. Mi ha aiutato a capire meglio stack/unstack. Grazie. – codingknob

1

Utilizzando il df2:

>>> df2.pivot_table(values='value', index=['DATE', 'variable'], columns="BORDER") 
BORDER    FRANCE GERMANY ITALY 
DATE  variable       
2014-01-01 HOUR1   2  2  2 
      HOUR2   3  3  3 
      HOUR3   8  8  8 
2014-01-02 HOUR1   4  4  4 
      HOUR2   5  5  5 
      HOUR3   12  12  12 
2014-01-03 HOUR1   6  6  6 
      HOUR2   7  7  7 
      HOUR3   99  99  99 

[9 rows x 3 columns] 

C'è ancora un po 'di pulizia da fare se si desidera convertire il "variabile" livello di indice in una colonna chiamata "ORA" e striscia fuori il testo "HOUR" dai valori, ma penso che sia il formato di base che desideri.