2014-10-21 16 views
9

Mam pandas DataFrame, df.pandy: pobierz elementy (indeks, kol) poniżej przekątnej w DataFrame

Chcę wyodrębnić listę wszystkich (col, index) w df, dla których wartość at (col, index)> .95.

Dodatkowo chcę uzależnić się od faktu, że znajdują się one w dolnej przekątnej df, nie licząc samej przekątnej. (Jeśli to pomaga, jest to korelacja df, więc przekątne to 1, co nie jest tym, co mnie interesuje.)

Jak mogę to zrobić?

+1

To interesujące - jestem ciekaw odpowiedzi też. Jestem świadomy numpy.diagonal(), ale wydaje się, że zwracają tylko wartości na przekątnej, a nie elementy pod nim .... – svenkatesh

Odpowiedz

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 

maskuje górny trójkąt (to przekątna)

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) 

Symulacja stanu (> 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 

Jest to prob postać chcesz wynikiem

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 

Jeśli naprawdę chcesz wartości pozycyjnych

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

Istnieje kilka sposobów maskowania wartości na górnej przekątnej za pomocą df.mask.

Jednym ze sposobów byłoby użycie np.triu. Ustawia wartości w prawym dolnym rogu tablicy na zero. Oto przykład:

>>> 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 

Poniższe wyrażenie produkuje taką samą DataFrame:

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

Następnie można zapytać nowego DataFrame w zwykły sposób. Na przykład:

>>> 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 

Aby uzyskać listę wskaźników żądanych wartości, oto jedna opcja:

>>> 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]]