2015-12-22 11 views
13

ein Quadrat Pandas Datenrahmen der folgenden Form gegeben:Melt die obere Dreiecksmatrix eines Pandas Dataframe

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

Wie kann ich melt nur das obere Dreieck

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  

Ich bin mehr zu bekommen Interesse an einer idiomatischen Pandas-Lösung, wäre ein benutzerdefinierter Indexer einfach genug, um von Hand zu schreiben ... Vielen Dank im Voraus für Ihre Berücksichtigung und Antwort.

Antwort

18

Zuerst konvertiere ich niedrigere Werte von df zu NaN von where und numpy.triu und dann stack, reset_index und setzen Spaltennamen:

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

Ich bin die einzige Sache, auf die ich achten muss, wenn Sie 'NaN' Werte haben, die Sie im oberen Dreieck beibehalten möchten (' stack' wird alle fallen lassen). Möglicherweise müssen Sie den Multiindex explizit erstellen und dann neu indizieren, wenn dies der Fall ist. –

4

Gebäude aus der Lösung durch @jezrael würde boolean Indizierung ein expliziter Ansatz sein:

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] 

Ausgang:

 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