2016-04-18 19 views
6

ho un frame di dati come questoPassando colonne in righe su pandi pitone

id a b c 
101 0 3 0 
102 2 0 5 
103 0 1 4 

e voglio qualcosa di simile

id letter num 
101  a  0 
101  b  3 
101  c  0 
102  a  2 
102  b  0 
102  c  5 
103  a  0 
103  b  1 
103  c  4 

voglio passare i nomi delle colonne di valori di una riga con il loro id corrispondente e il risultato del df.

Stavo cercando di farlo in un ciclo, introducendo ogni elemento in base al suo ID, ma è orribile. C'è un modo semplice per farlo?

risposta

6

Si potrebbe melt e poi scegli:

>>> pd.melt(df, id_vars='id', value_vars=['a','b','c'], 
      var_name='letter', value_name='num').sort_values('id') 
    id letter num 
0 101  a 0 
3 101  b 3 
6 101  c 0 
1 102  a 2 
4 102  b 0 
7 102  c 5 
2 103  a 0 
5 103  b 1 
8 103  c 4 

Se si desidera ripristinare l'indice, si può sempre usare .reset_index(drop=True) sul dataframe restituito.

+0

Questa soluzione è migliore del mio orribile per ciclo, vorrei solo aggiungere _value_vars_ invece di [ 'a', 'b', 'c'] -> ** Lista (df.columns [1:]) ** dal momento che avevo molte più colonne di solo a, b, c –

0

Probabilmente si desidera fare qualcosa sulla falsariga di

df2 = df.stack().reset_index(1) 

quindi rinominare le colonne

df.stack() produce una serie con un indice a più livelli:

In [5]: df.stack() 
Out[5]: 
id  
101 a 0 
    b 3 
    c 0 
102 a 2 
    b 0 
    c 5 
103 a 0 
    b 1 
    c 4 
dtype: int64 

Si desidera quindi suddividere questo indice a più livelli in colonne proprie. L'utilizzo di reset_index(1) lascia la colonna id come indice. Ma nota che le altre colonne hanno nomi sbagliati (corrispondenti ai loro precedenti livelli nell'indice a più livelli).

In [6]: df.stack().reset_index(1) 
Out[6]: 
    level_1 0 
id    
101  a 0 
101  b 3 
101  c 0 
102  a 2 
102  b 0 
102  c 5 
103  a 0 
103  b 1 
103  c 4 

Così li rinominare:

In [8]: df2.columns = ['letter', 'num'] 

In [9]: df2 
Out[9]: 
    letter num 
id    
101  a 0 
101  b 3 
101  c 0 
102  a 2 
102  b 0 
102  c 5 
103  a 0 
103  b 1 
103  c 4 
0

È possibile utilizzare ravel per rimodellare i valori di nuovo in una colonna.

df = pd.DataFrame({'id': [101, 102, 103], 
        'a': [0, 2, 0], 
        'b': [3, 0, 1], 
        'c': [0, 5, 4]})[['id', 'a', 'b', 'c']] 

>>> pd.DataFrame({'letter': df.columns[1:].tolist() * len(df), 
        'num': df.iloc[:, 1:].values.ravel()}) 
    letter num 
0  a 0 
1  b 3 
2  c 0 
3  a 2 
4  b 0 
5  c 5 
6  a 0 
7  b 1 
8  c 4 
Problemi correlati