2014-10-21 17 views
9

Ho un DataFrame panda, df.panda: ottieni elementi (indice, colonna) sotto diagonale in DataFrame

Voglio estrarre un elenco di tutti (col, indice) nel df per cui il valore in (colonna, indice)> .95.

Inoltre, voglio condizionare il fatto che si trovano nella diagonale inferiore del df, escludendo la diagonale stessa. (Se aiuta, è una correlazione df, quindi le diagonali sono 1 che non è quello che mi interessa.)

Come posso fare questo?

+1

Questo è interessante - Sono curioso di conoscere la risposta anche. Sono a conoscenza di numpy.diagonal(), ma sembra restituire solo i valori in diagonale, piuttosto che gli elementi al di sotto di esso .... – svenkatesh

risposta

7
In [71]: df = DataFrame(np.arange(25).reshape(5,5)) 

In [72]: df 
Out[72]: 
    0 1 2 3 4 
0 0 1 2 3 4 
1 5 6 7 8 9 
2 10 11 12 13 14 
3 15 16 17 18 19 
4 20 21 22 23 24 

Questa maschera il triangolo superiore (includere la diagonale)

In [73]: mask = np.ones(df.shape,dtype='bool') 

In [74]: mask[np.triu_indices(len(df))] = False 

In [75]: mask 
Out[75]: 
array([[False, False, False, False, False], 
     [ True, False, False, False, False], 
     [ True, True, False, False, False], 
     [ True, True, True, False, False], 
     [ True, True, True, True, False]], dtype=bool) 

Simulazione della condizione (> 0,95)

In [76]: df>16 
Out[76]: 
     0  1  2  3  4 
0 False False False False False 
1 False False False False False 
2 False False False False False 
3 False False True True True 
4 True True True True True 

Questa è prob la forma che si desidera che il risultato

In [77]: df[(df>16)&mask] 
Out[77]: 
    0 1 2 3 4 
0 NaN NaN NaN NaN NaN 
1 NaN NaN NaN NaN NaN 
2 NaN NaN NaN NaN NaN 
3 NaN NaN 17 NaN NaN 
4 20 21 22 23 NaN 

Se si vuole veramente i valori di posizione

In [78]: x = ((df>16)&mask).values.nonzero() 

In [79]: zip(x[0],x[1]) 
Out[79]: [(3, 2), (4, 0), (4, 1), (4, 2), (4, 3)] 
6

Ci sono un paio di modi per mascherare i valori nella diagonale superiore usando df.mask.

Un modo sarebbe utilizzare np.triu. Questo imposta i valori in basso a destra di una matrice su zero. Ecco un esempio:

>>> df = pd.DataFrame({'a': [3]*5, 'b': [2]*5, 'c': [1]*5, 'd': [0]*5, 'e': [6]*5}) 
>>> df 
    a b c d e 
0 3 2 1 0 6 
1 3 2 1 0 6 
2 3 2 1 0 6 
3 3 2 1 0 6 
4 3 2 1 0 6 

>>> df.mask(np.triu(np.ones(df.shape, dtype=np.bool_))) 
    a b c d e 
0 NaN NaN NaN NaN NaN 
1 3 NaN NaN NaN NaN 
2 3 2 NaN NaN NaN 
3 3 2 1 NaN NaN 
4 3 2 1 0 NaN 

La seguente espressione produce anche lo stesso dataframe:

df.mask(np.arange(df.shape[0]) >= np.arange(df.shape[1])[:, np.newaxis]) 

È quindi possibile interrogare questo nuovo dataframe nel solito modo. Per esempio:

>>> dfm = df.mask(np.triu(np.ones(df.shape, dtype=np.bool_))) 
>>> dfm[dfm > 1] 
    a b c d e 
0 NaN NaN NaN NaN NaN 
1 3 NaN NaN NaN NaN 
2 3 2 NaN NaN NaN 
3 3 2 NaN NaN NaN 
4 3 2 NaN NaN NaN 

per ottenere un elenco di indici dei vostri valori desiderati, ecco una possibilità:

>>> a = dfm[dfm > 1] 
>>> np.stack(a.notnull().values.nonzero()).T.tolist() 
[[1, 0], [2, 0], [2, 1], [3, 0], [3, 1], [4, 0], [4, 1]] 
Problemi correlati