2014-10-21 27 views
9

Tôi có một DataFrame gấu trúc, df.gấu trúc: lấy các phần tử (chỉ mục, col) bên dưới đường chéo trong DataFrame

Tôi muốn trích xuất danh sách tất cả (col, index) trong df mà giá trị tại (col, index)> .95.

Ngoài ra, tôi muốn điều kiện trên thực tế là chúng ở đường chéo dưới của df, không bao gồm chính đường chéo. (Nếu nó giúp, đó là một mối tương quan df, vì vậy các đường chéo là 1 mà không phải là những gì tôi quan tâm.)

Làm thế nào tôi có thể làm điều này?

+1

Đây là thú vị - Tôi tò mò muốn biết câu trả lời quá. Tôi biết về numpy.diagonal(), nhưng có vẻ như chỉ trả lại các giá trị ở đường chéo, chứ không phải là các phần tử bên dưới nó .... – svenkatesh

Trả lời

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 

mặt nạ này phía trên tam giác (bao gồm đường chéo)

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) 

Mô phỏng tình trạng của bạn (> 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 

Đây là prob dạng bạn muốn kết quả

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 

Nếu bạn thực sự muốn các giá trị vị trí

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

Có một vài cách bạn có thể che dấu các giá trị trong đường chéo trên bằng cách sử dụng df.mask.

Một cách là sử dụng np.triu. Điều này đặt các giá trị ở góc dưới bên phải của mảng thành 0. Dưới đây là một ví dụ:

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

Các biểu thức sau đây cũng sản xuất các DataFrame cùng:

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

Sau đó bạn có thể truy vấn DataFrame mới này theo cách thông thường. Ví dụ:

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

Để có được một danh sách các chỉ số của các giá trị mong muốn của bạn, đây là một lựa chọn:

>>> 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]] 
Các vấn đề liên quan