2017-04-13 23 views
7

Tôi đã đi qua một số câu hỏi trên StackOverflow nhưng không thể tìm thấy câu trả lời có liên quan. Tôi muốn tìm nạp chỉ mục của các giá trị lớn nhất k từ một số numpyndarray. This link thảo luận giống nhau nhưng đối với mảng 1D. np.argsort cho mảng 2D dẫn đến việc phân loại các yếu tố hàng khôn ngoan. tức làCách lấy chỉ mục giá trị lớn nhất của k từ một mảng nhiều chiều một chiều

Note: array elements are not unique. 

đầu vào:

import numpy as np 
n = np.arange(9).reshape(3,3) 
>>> n 
array([[0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8]]) 
s = n.argsort() 
>>> s 
array([[0, 1, 2], 
    [0, 1, 2], 
    [0, 1, 2]], dtype=int32) 

Ngoài ra,

import numpy as np 
n = np.arange(9).reshape(3,3) 
s = n.argsort(axis=None) 
>>>s 
array([0, 1, 2, 3, 4, 5, 6, 7, 8], dtype=int32) 

nhưng tôi mất cấu trúc mảng ở đây và không thể chuộc lại các chỉ số ban đầu của các yếu tố.

Mọi knid trợ giúp đều được đánh giá cao.

+0

nào bạn muốn một câu trả lời cho Mảng 2D cho mảng nD trong đó n> 2? – Chris

Trả lời

6

Couple các cách tiếp cận với np.argpartitionnp.argsort cho ndarrays -

def k_largest_index_argpartition_v1(a, k): 
    idx = np.argpartition(-a.ravel(),k)[:k] 
    return np.column_stack(np.unravel_index(idx, a.shape)) 

def k_largest_index_argpartition_v2(a, k): 
    idx = np.argpartition(a.ravel(),a.size-k)[-k:] 
    return np.column_stack(np.unravel_index(idx, a.shape)) 

def k_largest_index_argsort(a, k): 
    idx = np.argsort(a.ravel())[:-k-1:-1] 
    return np.column_stack(np.unravel_index(idx, a.shape)) 

Thảo luận về hai phiên bản với argpartition

Sự khác nhau giữa k_largest_index_argpartition_v1k_largest_index_argpartition_v2 là cách chúng ta đang sử dụng argparition. Trong phiên bản đầu tiên, chúng tôi đang phủ nhận mảng đầu vào và sau đó sử dụng argpartition để nhận chỉ mục cho các chỉ số k nhỏ nhất, do đó có hiệu quả các chỉ số lớn nhất k, trong khi ở phiên bản thứ hai, chúng tôi đang nhận được các chỉ số nhỏ nhất a.size-k đầu tiên và sau đó chúng tôi chọn chỉ số k lớn nhất còn sót lại.

Ngoài ra, đáng lưu ý ở đây là với argpartition, chúng tôi không nhận được các chỉ mục theo thứ tự được sắp xếp của chúng. Nếu cần phải sắp xếp thứ tự sắp xếp, chúng ta cần phải nạp vào mảng phạm vi đến np.argpartition, như được đề cập trong số post này.

mẫu chạy -

1) 2D trường hợp:

In [42]: a # 2D array 
Out[42]: 
array([[38, 14, 81, 50], 
     [17, 65, 60, 24], 
     [64, 73, 25, 95]]) 

In [43]: k_largest_index_argsort(a, k=2) 
Out[43]: 
array([[2, 3], 
     [0, 2]]) 

In [44]: k_largest_index_argsort(a, k=4) 
Out[44]: 
array([[2, 3], 
     [0, 2], 
     [2, 1], 
     [1, 1]]) 

In [66]: k_largest_index_argpartition_v1(a, k=4) 
Out[66]: 
array([[2, 1], # Notice the order is different 
     [2, 3], 
     [0, 2], 
     [1, 1]]) 

2) trường hợp 3D:

In [46]: a # 3D array 
Out[46]: 
array([[[20, 98, 27, 73], 
     [33, 78, 48, 59], 
     [28, 91, 64, 70]], 

     [[47, 34, 51, 19], 
     [73, 38, 63, 94], 
     [95, 25, 93, 64]]]) 

In [47]: k_largest_index_argsort(a, k=2) 
Out[47]: 
array([[0, 0, 1], 
     [1, 2, 0]]) 

Runtime thử nghiệm -

In [56]: a = np.random.randint(0,99999999999999,(3000,4000)) 

In [57]: %timeit k_largest_index_argsort(a, k=10) 
1 loops, best of 3: 2.18 s per loop 

In [58]: %timeit k_largest_index_argpartition_v1(a, k=10) 
10 loops, best of 3: 178 ms per loop 

In [59]: %timeit k_largest_index_argpartition_v2(a, k=10) 
10 loops, best of 3: 128 ms per loop 
+0

Điều này đã hiệu quả. Cảm ơn ngài. –

+0

Chỉ cần cho rõ ràng, 'argpartition' sẽ không cung cấp cho đầu' k' theo thứ tự, chỉ cần đầu 'k' trong thứ tự ban đầu của họ. Một cách để có tốt nhất của cả hai thế giới (tốc độ của 'argpartition', thứ tự của' argsort') là sắp xếp sau phân vùng: làm 'idx2 = np.argsort (-a.ravel() [idx])' và sau đó 'row, col = np.unravel.index (idx [idx2], a.shape)' –

+0

@DanielForsman Yup, đã thêm vài nhận xét về nó. – Divakar

Các vấn đề liên quan