2015-12-22 20 views
13

Dato un panda dataframe quadrato della forma seguente:Sciogliere il triangolare superiore Matrix di una Panda dataframe

a b c 
a 1 .5 .3 
b .5 1 .4 
c .3 .4 1 

Come posso melt solo il triangolo superiore per ottenere

Row  Column Value 
    a  a  1 
    a  b  .5 
    a  c  .3 
    b  b  1 
    b  c  .4 
    c  c  1 

#Note the combination a,b is only listed once. There is no b,a listing  

Sono più Interessato a una soluzione pandas idiomatica, un indicizzatore personalizzato sarebbe abbastanza facile da scrivere a mano ... Grazie in anticipo per la vostra considerazione e risposta.

risposta

18

Per prima cosa ho convertire i valori più bassi di df a NaN da where e numpy.triu e poi stack, reset_index e impostare i nomi delle colonne:

import numpy as np 

print df 
    a b c 
a 1.0 0.5 0.3 
b 0.5 1.0 0.4 
c 0.3 0.4 1.0 

print np.triu(np.ones(df.shape)).astype(np.bool) 
[[ True True True] 
[False True True] 
[False False True]] 

df = df.where(np.triu(np.ones(df.shape)).astype(np.bool)) 
print df 
    a b c 
a 1 0.5 0.3 
b NaN 1.0 0.4 
c NaN NaN 1.0 

df = df.stack().reset_index() 
df.columns = ['Row','Column','Value'] 
print df 

    Row Column Value 
0 a  a 1.0 
1 a  b 0.5 
2 a  c 0.3 
3 b  b 1.0 
4 b  c 0.4 
5 c  c 1.0 
+2

L'unica cosa a cui prestare attenzione è se si hanno valori di 'NaN' che si desidera conservare nel triangolo superiore (' stack' li lascerà tutti). Potrebbe essere necessario costruire esplicitamente il multiindice e quindi il reindex in questo caso. –

4

costruzione dalla soluzione da @jezrael, indicizzazione booleano sarebbe un approccio più esplicito:

import numpy 
from pandas import DataFrame 

df = DataFrame({'a':[1,.5,.3],'b':[.5,1,.4],'c':[.3,.4,1]},index=list('abc')) 
print df,'\n' 
keep = np.triu(np.ones(df.shape)).astype('bool').reshape(df.size) 
print df.stack()[keep] 

uscita:

 a b c 
a 1.0 0.5 0.3 
b 0.5 1.0 0.4 
c 0.3 0.4 1.0 

a a 1.0 
    b 0.5 
    c 0.3 
b b 1.0 
    c 0.4 
c c 1.0 
dtype: float64 
Problemi correlati