2015-12-22 24 views
13

Biorąc pod kwadratem pandy DataFrame z poniższego formularza:Melt Górne trójkątne matrycy Pandy Dataframe

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

Jak mogę melt tylko górny trójkąt, aby uzyskać

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  

Jestem bardziej zainteresowany rozwiązaniem idiomatycznej pandy, niestandardowy indeksator byłby łatwy do napisania ręcznie ... Z góry dziękuję za uwagę i odpowiedź.

Odpowiedz

18

Najpierw przekonwertować niższe wartości df do NaN przez where i numpy.triu a następnie stack, reset_index i ustawić nazwy kolumn:

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

Jedyną rzeczą, na którą należy zwrócić uwagę, jest to, że posiadasz wartości 'NaN', które chcesz zachować w górnym trójkącie (' stack' spowoduje ich upuszczenie). Być może będziesz musiał jawnie skonstruować indeks wielowierszowy, a następnie ponownie utworzyć indeks, jeśli tak jest. –

4

budynku z roztworu przez @jezrael, indeksowanie logiczna byłaby bardziej wyraźne podejście:

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] 

wyjściowa:

 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