Numpy Argsort - มันทำอะไร?


123

ทำไม numpy จึงให้ผลลัพธ์นี้:

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

>[2 3 1 0]

เมื่อฉันคาดหวังว่าจะทำสิ่งนี้:

[3 2 0 1]

เห็นได้ชัดว่าฉันขาดความเข้าใจเกี่ยวกับฟังก์ชันนี้


6
ทำไมคุณถึงคิดว่า[3 2 0 1]เป็นคำตอบที่ถูกต้อง
zwol

9
ฉันมีความเข้าใจแบบกลับหัวของผลลัพธ์ กล่าวคือถ้าคุณใช้องค์ประกอบแรกของ x มันควรอยู่ในตำแหน่ง 3 ของอาร์เรย์ที่เรียงลำดับไปเรื่อย ๆ
user1276273

26
วิธีคิดของคุณเข้าท่าโดยสิ้นเชิงฉันมีคำถามเดียวกัน
adrienlucca.wordpress.com

2
[3 2 0 1] - นี่คือการจัดอันดับค่าคุณไม่ได้รับดัชนีจริง
Lahiru Karunaratne

เพียงจำไว้ว่าผลลัพธ์ระบุตำแหน่งในอาร์เรย์เดิมในขณะที่คุณคิดว่าอยู่ในอาร์เรย์ที่เรียงลำดับ นั่นหมายความว่าเอาต์พุต [0] คือดัชนีที่องค์ประกอบที่เล็กที่สุดในอาร์เรย์อินพุตดั้งเดิมระบุตำแหน่งและเอาต์พุต [-1] สำหรับองค์ประกอบที่ใหญ่ที่สุด
lincr

คำตอบ:


144

ตามเอกสารประกอบ

ส่งคืนดัชนีที่จะจัดเรียงอาร์เรย์

  • 20.0เป็นดัชนีของ
  • 30.1เป็นดัชนีของ
  • 11.41เป็นดัชนีของ
  • 01.48เป็นดัชนีของ

12
a = x.argsort()พิมพ์x[a]เราจะได้รับarray([ 0. , 0.1 , 1.41, 1.48])
Belter

39

[2, 3, 1, 0] บ่งชี้ว่าองค์ประกอบที่เล็กที่สุดอยู่ที่ดัชนี 2 ซึ่งเป็นดัชนีที่เล็กที่สุดถัดไปที่ดัชนี 3 จากนั้นดัชนี 1 จากนั้นดัชนี 0

มีหลายวิธีในการรับผลลัพธ์ที่คุณต้องการ:

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

ตัวอย่างเช่น,

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

สิ่งนี้จะตรวจสอบว่าทั้งหมดให้ผลลัพธ์เดียวกัน:

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

%timeitเกณฑ์มาตรฐานIPython เหล่านี้แนะนำสำหรับอาร์เรย์ขนาดใหญ่using_indexed_assignmentนั้นเร็วที่สุด:

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

สำหรับอาร์เรย์ขนาดเล็กusing_argsort_twiceอาจเร็วกว่า:

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

โปรดทราบว่าstats.rankdataช่วยให้คุณควบคุมวิธีจัดการองค์ประกอบที่มีมูลค่าเท่ากันได้มากขึ้น


1
คุณสามารถเพิ่มคำอธิบายว่าทำไมการใช้ argsort () สองครั้งจึงทำให้เราได้อันดับ
Phani

1
@Phani: argsortส่งคืนดัชนีของอาร์เรย์ที่เรียงลำดับ ดัชนีของดัชนีที่เรียงลำดับคืออันดับ นี่คือสิ่งที่เรียกร้องให้argsortกลับมาครั้งที่สอง
unutbu

2
argsort แรกส่งคืนการเปลี่ยนแปลง (ซึ่งถ้าใช้กับข้อมูลจะเรียงลำดับ) เมื่ออาร์กซอร์ทถูกนำไปใช้กับ (สิ่งนี้หรือใด ๆ ) การเรียงสับเปลี่ยนมันจะส่งกลับการเปลี่ยนแปลงแบบผกผัน (ซึ่งหากใช้ 2 การเรียงสับเปลี่ยนกันในลำดับใดลำดับหนึ่งผลลัพธ์คือ Identity) การเปลี่ยนแปลงที่สองหากนำไปใช้กับอาร์เรย์ข้อมูลที่เรียงลำดับจะทำให้เกิดอาร์เรย์ข้อมูลที่ไม่เรียงลำดับกล่าวคือเป็นอันดับ
Alex C

1
ใจเป่า ในที่สุดฉันก็เข้าใจแล้ว! ส่งคืนอาร์เรย์ที่มีเนื้อหาเป็นดัชนีของอาร์เรย์เดิมตามลำดับที่เรียงลำดับ
Jose A

3

ตามเอกสารระบุว่าargsort:

ส่งคืนดัชนีที่จะจัดเรียงอาร์เรย์

นั่นหมายความว่าองค์ประกอบแรกของ argsort คือดัชนีขององค์ประกอบที่ควรเรียงลำดับก่อนองค์ประกอบที่สองคือดัชนีขององค์ประกอบที่ควรเป็นอันดับสองเป็นต้น

scipy.stats.rankdataสิ่งที่คุณดูเหมือนจะต้องการเป็นลำดับของค่าซึ่งเป็นสิ่งที่ให้บริการโดย โปรดทราบว่าคุณต้องคิดถึงสิ่งที่จะเกิดขึ้นหากมีความสัมพันธ์ในอันดับ


3

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

ส่งคืนดัชนีที่จะจัดเรียงอาร์เรย์

ดำเนินการจัดเรียงทางอ้อมตามแกนที่กำหนดโดยใช้อัลกอริทึมที่ระบุโดยคีย์เวิร์ดชนิด ส่งคืนอาร์เรย์ของดัชนีที่มีรูปร่างเดียวกันกับข้อมูลดัชนีตามแกนที่กำหนดตามลำดับที่จัดเรียง

พิจารณาตัวอย่างหนึ่งใน python ซึ่งมีรายการค่าเป็น

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

ตอนนี้เราใช้ฟังก์ชัน argsort:

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

ผลลัพธ์จะเป็น

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

นี่คือรายการดัชนีของค่าใน listExam ตัวอย่างหากคุณจับคู่ดัชนีเหล่านี้กับค่าตามลำดับเราจะได้ผลลัพธ์ดังนี้:

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

(ฉันพบว่าฟังก์ชันนี้มีประโยชน์มากในหลาย ๆ ที่เช่นหากคุณต้องการจัดเรียงรายการ / อาร์เรย์ แต่ไม่ต้องการใช้ฟังก์ชัน list.sort () (เช่นโดยไม่ต้องเปลี่ยนลำดับของค่าจริงในรายการ) คุณสามารถใช้สิ่งนี้ได้ ฟังก์ชั่น.)

สำหรับรายละเอียดเพิ่มเติมโปรดดูที่ลิงค์นี้: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html


1

อินพุต:
นำเข้า numpy เป็น np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()

เอาต์พุต:
อาร์เรย์ ([3, 2, 0, 1])


1
แม้ว่าข้อมูลโค้ดนี้อาจเป็นวิธีแก้ปัญหา แต่การมีคำอธิบายจะช่วยปรับปรุงคุณภาพของโพสต์ของคุณได้มาก โปรดจำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและบุคคลเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำโค้ดของคุณ
peacetype


0

np.argsort ส่งคืนดัชนีของอาร์เรย์ที่เรียงลำดับตาม 'ชนิด' (ซึ่งระบุประเภทของอัลกอริทึมการเรียงลำดับ) อย่างไรก็ตามเมื่อรายการถูกใช้กับ np.argmax จะส่งกลับดัชนีขององค์ประกอบที่ใหญ่ที่สุดในรายการ ในขณะที่ np.sort จัดเรียงอาร์เรย์ที่กำหนดรายการ


0

เพียงแค่ต้องการเปรียบเทียบความเข้าใจดั้งเดิมของ OP โดยตรงกับการใช้งานจริงด้วยโค้ด

numpy.argsort ถูกกำหนดไว้สำหรับอาร์เรย์ 1D:

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

เดิมที OP คิดว่ามันถูกกำหนดไว้สำหรับอาร์เรย์ 1D:

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

หมายเหตุ:รหัสนี้ใช้ไม่ได้ในกรณีทั่วไป (ใช้ได้กับ 1D เท่านั้น) คำตอบนี้ใช้เพื่อจุดประสงค์ในการอธิบายเท่านั้น


x[x.argsort()]np.sort(x)ไม่จำเป็นต้องเป็นเช่นเดียวกับ จริงๆแล้วมันไม่จำเป็นต้องมีรูปร่างเหมือนกันด้วยซ้ำ ลองใช้อาร์เรย์ 2D สิ่งนี้เกิดขึ้นกับอาร์เรย์ 1D เท่านั้น
นาธาน

ฉันรู้สึกว่ามันอวดดีโดยไม่จำเป็น คำถามคือเกี่ยวกับอาร์เรย์ 1D สิ่งนี้มีไว้เพื่อทำความเข้าใจว่าความแตกต่างคืออะไรแทนที่จะใช้รหัสตามตัวอักษร นอกจากนี้เมื่อคุณมีอาร์เรย์ 2 มิติก็ยังไม่ชัดเจนว่าคุณต้องการจัดเรียงแบบใด คุณต้องการจัดเรียงทั่วโลกหรือไม่? ถ้าไม่ควรเรียงแกนใด ฉันได้เพิ่มข้อจำกัดความรับผิดชอบแล้ว
Multihunter

0

มันส่งคืนดัชนีตามดัชนีอาร์เรย์ที่กำหนด[1.48,1.41,0.0,0.1]นั่นหมายถึง: 0.0เป็นองค์ประกอบแรกในดัชนี [2] 0.1เป็นองค์ประกอบที่สองในดัชนี [3] 1.41เป็นองค์ประกอบที่สามในดัชนี [1] 1.48เป็นองค์ประกอบที่สี่ในดัชนี [0] เอาท์พุท:

[2,3,1,0]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.