2013-07-27 11 views
63

Tại sao NumPy đưa ra kết quả này:Numpy argsort - nó đang làm gì?

x = numpy.array([1.48,1.41,0.0,0.1]) 
print x.argsort() 

>[2 3 1 0] 

khi tôi mong đợi nó để làm điều này:

[3 2 0 1]

Rõ ràng sự hiểu biết của tôi về chức năng thiếu hụt.

+2

Tại sao bạn nghĩ '[3 2 0 1]' sẽ là câu trả lời đúng? – zwol

+6

Tôi vừa có một sự hiểu biết ngược về đầu ra. Tức là, nếu bạn lấy phần tử đầu tiên của x, nó sẽ ở vị trí thứ 3 của một mảng được sắp xếp và cứ thế. – user1276273

+11

cách suy nghĩ của bạn hoàn toàn hợp lý, tôi đã có cùng một câu hỏi –

Trả lời

67

Theo the documentation

Trả về chỉ số đó sẽ sắp xếp một mảng.

  • 2 là chỉ số của 0.0.
  • 3 là chỉ mục của 0.1.
  • 1 là chỉ mục của 1.41.
  • 0 là chỉ mục của 1.48.
+3

'a = x.argsort()', in 'x [a]', chúng ta sẽ nhận được 'mảng ([0., 0.1, 1.41, 1.48])' – Belter

21

[2, 3, 1, 0] chỉ ra rằng yếu tố nhỏ nhất là ở chỉ số 2, nhỏ nhất tiếp theo tại chỉ số 3, sau đó chỉ số 1, sau đó chỉ số 0.

a number of ways để có được kết quả bạn đang tìm kiếm:

import numpy as np 
import scipy.stats as stats 

def using_indexed_assignment(x): 
    "https://stackoverflow.com/a/5284703/190597 (Sven Marnach)" 
    result = np.empty(len(x), dtype=int) 
    temp = x.argsort() 
    result[temp] = np.arange(len(x)) 
    return result 

def using_rankdata(x): 
    return stats.rankdata(x)-1 

def using_argsort_twice(x): 
    "https://stackoverflow.com/a/6266510/190597 (k.rooijers)" 
    return np.argsort(np.argsort(x)) 

def using_digitize(x): 
    unique_vals, index = np.unique(x, return_inverse=True) 
    return np.digitize(x, bins=unique_vals) - 1 

Ví dụ,

In [72]: x = np.array([1.48,1.41,0.0,0.1]) 

In [73]: using_indexed_assignment(x) 
Out[73]: array([3, 2, 0, 1]) 

này kiểm tra rằng tất cả họ đều tạo ra kết quả tương tự:

x = np.random.random(10**5) 
expected = using_indexed_assignment(x) 
for func in (using_argsort_twice, using_digitize, using_rankdata): 
    assert np.allclose(expected, func(x)) 

Những tiêu chuẩn IPython %timeit gợi ý cho mảng lớn using_indexed_assignment là nhanh nhất:

In [50]: x = np.random.random(10**5) 
In [66]: %timeit using_indexed_assignment(x) 
100 loops, best of 3: 9.32 ms per loop 

In [70]: %timeit using_rankdata(x) 
100 loops, best of 3: 10.6 ms per loop 

In [56]: %timeit using_argsort_twice(x) 
100 loops, best of 3: 16.2 ms per loop 

In [59]: %timeit using_digitize(x) 
10 loops, best of 3: 27 ms per loop 

Đối với mảng nhỏ, using_argsort_twice có thể nhanh hơn:

In [78]: x = np.random.random(10**2) 

In [81]: %timeit using_argsort_twice(x) 
100000 loops, best of 3: 3.45 µs per loop 

In [79]: %timeit using_indexed_assignment(x) 
100000 loops, best of 3: 4.78 µs per loop 

In [80]: %timeit using_rankdata(x) 
100000 loops, best of 3: 19 µs per loop 

In [82]: %timeit using_digitize(x) 
10000 loops, best of 3: 26.2 µs per loop 

Cũng lưu ý rằng stats.rankdata cho phép bạn kiểm soát nhiều hơn cách xử lý các phần tử có giá trị như nhau.

+0

Bạn có thể thêm một số giải thích về lý do tại sao áp dụng argsort() hai lần cho chúng ta thứ hạng không? – Phani

+0

@Phani: 'argsort' trả về chỉ số của mảng được sắp xếp. Chỉ số của các chỉ số được sắp xếp là thứ hạng. Đây là lời gọi thứ hai để trả về 'argsort'. – unutbu

+2

argsort đầu tiên trả về một hoán vị (nếu áp dụng cho dữ liệu sẽ sắp xếp nó). Khi argsort được áp dụng cho hoán vị (này hoặc bất kỳ), nó trả về hoán vị nghịch đảo (nếu 2 hoán vị được áp dụng cho nhau theo thứ tự thì kết quả là Định danh). Phép hoán vị thứ hai nếu được áp dụng cho một mảng dữ liệu được sắp xếp sẽ tạo ra mảng dữ liệu chưa được phân loại, tức là nó là thứ hạng. –

2

Như the documentation nói, argsort:

Trả về chỉ số đó sẽ sắp xếp một mảng.

Điều đó có nghĩa là yếu tố đầu tiên của argsort là chỉ số của phần tử cần được sắp xếp đầu tiên, yếu tố thứ hai là chỉ số của phần tử cần được thứ hai vv

gì bạn dường như muốn là thứ tự xếp hạng của các giá trị, đó là thứ được cung cấp bởi scipy.stats.rankdata. Lưu ý rằng bạn cần phải suy nghĩ về những gì sẽ xảy ra nếu có quan hệ trong hàng ngũ.

+0

Có - cảm ơn. Đó là những gì tôi đã giả định nó sẽ cho kết quả là. Cách nó hoạt động là hoàn toàn tốt đẹp cho việc sử dụng của tôi, tôi chỉ không hiểu nó. Không đủ cà phê có lẽ ... – user1276273

0

Đầu tiên, nó được đặt hàng mảng. Sau đó tạo một mảng với chỉ mục ban đầu của mảng.

+0

Vui lòng trả lời bằng mã lặp lại –

0

Chỉ muốn tương phản trực tiếp sự hiểu biết ban đầu của OP đối với việc triển khai thực tế bằng mã.

numpy.argsort được xác định sao cho

x[x.argsort()] == numpy.sort(x) # this will be an array of True's 

Các OP ban đầu nghĩ rằng nó đã được xác định sao cho

x == numpy.sort(x)[x.argsort()] # this will not be True 
0

đầu vào:
nhập khẩu NumPy như np
x = np.array ([ 1.48,1.41,0.0,0.1])
x.argsort(). Argsort()

đầu ra:
mảng ([3, 2, 0, 1])

+0

Mặc dù đoạn mã này có thể là giải pháp, [bao gồm giải thích] (// meta.stackexchange.com/questions/114762/explaining-entirely-‌ code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. – peacetype