Numpy argsort - nó đang làm gì vậy?


123

Tại sao numpy lại đưa ra kết quả này:

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 là sự hiểu biết của tôi về chức năng này còn thiếu sót.


6
Tại sao bạn nghĩ [3 2 0 1]sẽ là câu trả lời chính xác?
zwol

9
Tôi chỉ 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ó phải ở vị trí 3 của một mảng đã sắp xếp, v.v.
user1276273

26
cách suy nghĩ của bạn hoàn toàn có lý, tôi cũng có câu hỏi tương tự
adrienlucca.wordpress.com

2
[3 2 0 1] - đây là xếp hạng các giá trị, bạn không nhận được các chỉ số thực tế.
Lahiru Karunaratne

Chỉ cần nhớ rằng đầu ra chỉ ra các vị trí trong mảng ban đầu trong khi bạn nghĩ rằng nó nằm trong mảng đã sắp xếp. Điều đó có nghĩa là đầu ra [0] là chỉ số nơi phần tử nhỏ nhất trong mảng đầu vào ban đầu định vị và đầu ra [-1] cho phần tử lớn nhất.
lincr

Câu trả lời:


143

Theo tài liệu

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

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

12
a = x.argsort(), in x[a], chúng tôi sẽ nhận đượcarray([ 0. , 0.1 , 1.41, 1.48])
Belter

39

[2, 3, 1, 0] chỉ ra rằng phần tử nhỏ nhất ở chỉ số 2, nhỏ nhất tiếp theo ở chỉ số 3, sau đó là chỉ số 1, rồi đến chỉ số 0.

một số cách để có được kết quả mà 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])

Điều này kiểm tra rằng tất cả chúng đều tạo ra cùng một kết quả:

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

Các %timeitđiểm chuẩn IPython này gợi ý cho các mảng lớn using_indexed_assignmentlà 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 các mảng nhỏ, using_argsort_twicecó 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.rankdatacung cấp cho bạn nhiều quyền kiểm soát hơn đối với cách xử lý các phần tử có giá trị bằng nhau.


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

1
@Phani: argsorttrả về các chỉ số của mảng đã sắp xếp. Chỉ số của các chỉ số được sắp xếp là thứ hạng. Đây là những gì cuộc gọi thứ hai để argsorttrả về.
unutbu

2
Argsort đầu tiên trả về một hoán vị (nếu được áp dụng cho dữ liệu sẽ sắp xếp nó). Khi argsort được áp dụng cho (này hoặc bất kỳ) hoán vị nào, nó sẽ trả về hoán vị nghịch đảo (nếu 2 hoán vị được áp dụng cho nhau theo một trong hai thứ tự thì kết quả là Identity). 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 không được sắp xếp, tức là nó là thứ hạng.
Alex C

1
Tâm trí bị thổi bay. Cuối cùng thì tôi cũng hiểu ra rồi! Nó trả về một mảng có nội dung là các chỉ số của mảng ban đầu theo thứ tự được sắp xếp.
Jose A

3

Như tài liệu cho biết argsort:

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

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

Những gì bạn có vẻ 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 suy nghĩ về những gì sẽ xảy ra nếu có ràng buộc trong hàng ngũ.


3

numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)

Trả về các chỉ số sẽ sắp xếp một mảng

Thực hiện sắp xếp gián tiếp dọc theo trục đã cho bằng cách sử dụng thuật toán được chỉ định bởi từ khóa kind. Nó trả về một mảng các chỉ số có cùng hình dạng với dữ liệu chỉ mục đó dọc theo trục đã cho theo thứ tự được sắp xếp.

Hãy xem xét một ví dụ trong python, có danh sách các giá trị như

listExample  = [0 , 2, 2456,  2000, 5000, 0, 1]

Bây giờ chúng ta sử dụng hàm argsort:

import numpy as np
list(np.argsort(listExample))

Đầu ra sẽ là

[0, 5, 6, 1, 3, 2, 4]

Đây là danh sách các chỉ số của giá trị trong listVí dụ nếu bạn ánh xạ các chỉ số này với các giá trị tương ứng thì chúng ta sẽ nhận được kết quả như sau:

[0, 0, 1, 2, 2000, 2456, 5000]

(Tôi thấy hàm này rất hữu ích ở nhiều nơi, ví dụ: Nếu bạn muốn sắp xếp danh sách / mảng nhưng không muốn sử dụng hàm list.sort () (tức là không thay đổi thứ tự của các giá trị thực trong danh sách), bạn có thể sử dụng hàm này chức năng.)

Để biết thêm chi tiết, hãy tham khảo liên kết này: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html


1

input:
import numpy as np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()

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


1
Mặc dù đoạn mã này có thể là giải pháp, nhưng bao gồm lời giải thích 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

0

Đầu tiên, nó được sắp xếp theo thứ tự mảng. Sau đó, tạo một mảng với chỉ số ban đầu của mảng.


0

np.argsort trả về chỉ số của mảng đã sắp xếp được cung cấp bởi 'loại' (chỉ định loại thuật toán sắp xếp). Tuy nhiên, khi một danh sách được sử dụng với np.argmax, nó sẽ trả về chỉ mục của phần tử lớn nhất trong danh sách. Trong khi, np.sort, sắp xếp mảng, danh sách đã cho.


0

Chỉ muốn đối chiếu trực tiếp hiểu biết ban đầu của OP với cách triển khai thực tế với mã.

numpy.argsort được định nghĩa như vậy đối với mảng 1D:

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

OP ban đầu nghĩ rằng nó được định nghĩa như vậy đối với mảng 1D:

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

Lưu ý: Mã này không hoạt động trong trường hợp chung (chỉ hoạt động cho 1D), câu trả lời này hoàn toàn mang tính chất minh họa.


x[x.argsort()]không nhất thiết phải giống như np.sort(x). Trên thực tế, nó không nhất thiết phải có hình dạng giống nhau. Hãy thử điều này với một mảng 2D. Điều này chỉ xảy ra với các mảng 1D.
Nathan

Tôi cảm thấy như vậy là không cần thiết. Câu hỏi là về mảng 1D. Đây là một cách để hiểu sự khác biệt là gì, thay vì sử dụng mã theo nghĩa đen. Ngoài ra, khi bạn có mảng 2D, bạn thậm chí không rõ loại sắp xếp nào bạn muốn. Bạn có muốn phân loại toàn cầu không? Nếu không, trục nào nên được sắp xếp? Bất kể, tôi đã thêm một tuyên bố từ chối trách nhiệm.
Multihunter

0

Nó trả về các chỉ số theo các chỉ số mảng đã cho [1.48,1.41,0.0,0.1], có nghĩa là: 0.0là phần tử đầu tiên, trong chỉ mục [2]. 0.1là phần tử thứ hai, trong chỉ mục [3]. 1.41là phần tử thứ ba, trong chỉ mục [1]. 1.48là phần tử thứ tư, trong chỉ mục [0]. Đầu ra:

[2,3,1,0]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.