เรียงลำดับอาร์เรย์จำนวนมากอย่างมีประสิทธิภาพหรือไม่?


121

ฉันกำลังประหลาดใจคำถามเฉพาะนี้ยังไม่ได้รับการถามก่อน np.sortแต่ผมไม่คิดว่ามันในดังนั้นไม่เกี่ยวกับเอกสารของ

สมมติว่าฉันมีอาร์เรย์แบบสุ่มที่ถือจำนวนเต็มเช่น:

> temp = np.random.randint(1,10, 10)    
> temp
array([2, 4, 7, 4, 2, 2, 7, 6, 4, 4])

ถ้าฉันเรียงลำดับฉันจะเรียงลำดับจากน้อยไปมากโดยค่าเริ่มต้น:

> np.sort(temp)
array([2, 2, 2, 4, 4, 4, 4, 6, 7, 7])

แต่ฉันต้องการแก้ปัญหาที่จะเรียงจากมากไปน้อยการสั่งซื้อ

ตอนนี้ฉันรู้ว่าฉันทำได้เสมอ:

reverse_order = np.sort(temp)[::-1]

แต่คำสั่งสุดท้ายนี้มีประสิทธิภาพหรือไม่? มันไม่ได้สร้างสำเนาจากน้อยไปหามากแล้วย้อนกลับสำเนานี้เพื่อให้ได้ผลลัพธ์ในลำดับที่กลับกันใช่หรือไม่? หากเป็นเช่นนั้นจริงมีทางเลือกอื่นที่มีประสิทธิภาพหรือไม่? ดูเหมือนไม่np.sortยอมรับพารามิเตอร์เพื่อเปลี่ยนเครื่องหมายของการเปรียบเทียบในการดำเนินการเรียงลำดับเพื่อให้ได้สิ่งต่างๆในลำดับย้อนกลับ

คำตอบ:


139

temp[::-1].sort()เรียงลำดับอาร์เรย์ในขณะที่np.sort(temp)[::-1]สร้างอาร์เรย์ใหม่

In [25]: temp = np.random.randint(1,10, 10)

In [26]: temp
Out[26]: array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

In [27]: id(temp)
Out[27]: 139962713524944

In [28]: temp[::-1].sort()

In [29]: temp
Out[29]: array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

In [30]: id(temp)
Out[30]: 139962713524944

30
ขอบคุณ แต่จะtemp[::-1].sort()รู้ได้อย่างไรว่าต้องเรียงลำดับย้อนกลับ ?? วิธีที่ฉันอ่านคือ: ย้อนกลับอาร์เรย์เดิมแล้วเรียงลำดับ (จากน้อยไปมาก) เหตุใดการย้อนกลับอาร์เรย์เดิม (มาในลำดับสุ่ม) แล้วการเรียงลำดับจากน้อยไปมากจะส่งกลับอาร์เรย์ในลำดับย้อนกลับ
Amelio Vazquez-Reina

14
พฤติกรรมนี้ได้รับการบันทึกไว้หรือไม่เนื่องจากค่อนข้างไม่เข้าใจง่าย
ebarr

18
ดูเหมือนว่าจะใช้งานได้เพราะ[::-1]เพียงแค่บอกว่า numpy ให้วนซ้ำอาร์เรย์ไปข้างหลังแทนที่จะเรียงลำดับอาร์เรย์ใหม่จริงๆ ดังนั้นเมื่อการจัดเรียงในสถานที่เกิดขึ้นจริงมันจะเรียงลำดับจากน้อยไปมากและย้ายบิตไปรอบ ๆ แต่ปล่อยให้ส่วนการทำซ้ำย้อนกลับโดยไม่ถูกแตะต้อง
perimosocordiae

46
ด้วยa=np.array((...))สำนวนa[::-1]ไม่ได้ย้อนกลับอะไรเลยมันเป็นเพียงมุมมองใหม่ในข้อมูลเดียวกันโดยเฉพาะอย่างยิ่งมุมมองกระจก วิธีการนี้a[::-1].sort() ทำงานบนภาพมิเรอร์ซึ่งหมายความว่าเมื่อsortย้ายไปทางซ้ายของรายการที่มีขนาดเล็กกว่าในภาพที่มิเรอร์ในความเป็นจริงมันจะย้ายไปทางขวาในบล็อกหน่วยความจำจริงของaอาร์เรย์ มุมมองแบบมิเรอร์จะเรียงลำดับจากน้อยไปมากข้อมูลจริงจะเรียงลำดับจากมากไปหาน้อย ลองทำที่บ้านด้วยตัวเองด้วยเหรียญและกระจกที่แตกต่างกัน!
gboffi

30
สิ่งนี้ควรเพิ่มเป็นพารามิเตอร์ที่อ่านได้เช่นnp.sort(temp,order='descending')แทนที่จะต้องใช้แฮ็กประเภทนี้
นาธาน

92
>>> a=np.array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

>>> np.sort(a)
array([2, 2, 4, 4, 4, 4, 5, 6, 7, 8])

>>> -np.sort(-a)
array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

2
คำตอบที่ดีที่สุด - สั้นและไพเราะและไม่จำเป็นต้องมีความรู้เกี่ยวaxisกับสิ่งที่np.sortนำไปใช้
Luke Davis

2
สิ่งนี้แตกต่างจากตรงnp.sort(temp)[::-1]ที่วางnans ไว้ที่ด้านหลังของอาร์เรย์แทนที่จะเป็นด้านหน้า ไม่ว่าจะดีหรือไม่ดีขึ้นอยู่กับการถกเถียง ..
เบ็น

15

สำหรับอาร์เรย์แบบสั้นฉันขอแนะนำให้ใช้np.argsort()โดยการค้นหาดัชนีของอาร์เรย์เชิงลบที่เรียงลำดับซึ่งเร็วกว่าการย้อนกลับอาร์เรย์ที่เรียงลำดับเล็กน้อย:

In [37]: temp = np.random.randint(1,10, 10)

In [38]: %timeit np.sort(temp)[::-1]
100000 loops, best of 3: 4.65 µs per loop

In [39]: %timeit temp[np.argsort(-temp)]
100000 loops, best of 3: 3.91 µs per loop

a[np.argsort(-a)]น่าจะเป็นแนวทางที่ดีที่สุดสำหรับผู้อื่นในหน้านี้ ไม่มีการกลับตัว -1 ขั้นตอนและเครื่องหมายลบน้อยกว่าที่จะคิด
Jarad

8

น่าเสียดายที่เมื่อคุณมีอาร์เรย์ที่ซับซ้อนจะnp.sort(temp)[::-1]ทำงานได้ดีเท่านั้น อีกสองวิธีที่กล่าวถึงนี้ไม่ได้ผล


@ anishtain4: โดย "อาร์เรย์เชิงซ้อน" คุณหมายถึงอาร์เรย์ของจำนวนเชิงซ้อนหรือไม่? หรือคุณหมายถึงอาร์เรย์ที่มีความซับซ้อนประเภทอื่น (ถ้าเป็นเช่นนั้นกรุณาระบุประเภทของความซับซ้อน) ไม่ว่าในกรณีใดฉันรู้สึกว่าคุณสามารถอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับคำตอบของคุณได้โดยดูว่าวิธีการอื่น ๆ อาจล้มเหลวได้อย่างไร ขอบคุณ
Fountainhead

@fountainhead ฉันหมายถึงอาร์เรย์ของจำนวนเชิงซ้อน เนื่องจากเป็นคำถามเก่าฉันจำกรณีทดสอบของฉันไม่ได้จากนั้นจึงอธิบายเพิ่มเติม
anishtain4

8

ระวังมิติด้วย

ปล่อย

x  # initial numpy array
I = np.argsort(x) or I = x.argsort() 
y = np.sort(x)    or y = x.sort()
z  # reverse sorted array

ย้อนกลับแบบเต็ม

z = x[-I]
z = -np.sort(-x)
z = np.flip(y)
  • flipการเปลี่ยนแปลงใน1.15รุ่นก่อนหน้านี้จำเป็นต้องใช้ วิธีแก้ไข: .1.14 axispip install --upgrade numpy

ย้อนกลับมิติแรก

z = y[::-1]
z = np.flipud(y)
z = np.flip(y, axis=0)

มิติที่สองกลับด้าน

z = y[::-1, :]
z = np.fliplr(y)
z = np.flip(y, axis=1)

การทดสอบ

การทดสอบบนอาร์เรย์ 100 × 10 × 10 1,000 ครั้ง

Method       | Time (ms)
-------------+----------
y[::-1]      | 0.126659  # only in first dimension
-np.sort(-x) | 0.133152
np.flip(y)   | 0.121711
x[-I]        | 4.611778

x.sort()     | 0.024961
x.argsort()  | 0.041830
np.flip(x)   | 0.002026

นี้เป็นส่วนใหญ่เนื่องจากการ reindexing argsortมากกว่า

# Timing code
import time
import numpy as np


def timeit(fun, xs):
    t = time.time()
    for i in range(len(xs)):  # inline and map gave much worse results for x[-I], 5*t
        fun(xs[i])
    t = time.time() - t
    print(np.round(t,6))

I, N = 1000, (100, 10, 10)
xs = np.random.rand(I,*N)
timeit(lambda x: np.sort(x)[::-1], xs)
timeit(lambda x: -np.sort(-x), xs)
timeit(lambda x: np.flip(x.sort()), xs)
timeit(lambda x: x[-x.argsort()], xs)
timeit(lambda x: x.sort(), xs)
timeit(lambda x: x.argsort(), xs)
timeit(lambda x: np.flip(x), xs)

np.flip () - super
Darius

6

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

x=np.sort(array)
y=np.fliplr(x)

np.sort เรียงลำดับจากน้อยไปมากซึ่งไม่ใช่สิ่งที่คุณต้องการ แต่คำสั่ง fliplr จะพลิกแถวจากซ้ายไปขวา! ดูเหมือนจะได้ผล!

หวังว่ามันจะช่วยคุณได้!

ฉันเดาว่ามันคล้ายกับคำแนะนำเกี่ยวกับ -np.sort (-a) ด้านบน แต่ฉันถูกเลื่อนออกไปโดยแสดงความคิดเห็นว่ามันไม่ได้ผลเสมอไป บางทีโซลูชันของฉันอาจไม่ได้ผลเสมอไปอย่างไรก็ตามฉันได้ทดสอบกับอาร์เรย์สองสามอาร์เรย์และดูเหมือนว่าจะใช้ได้


1

คุณสามารถจัดเรียงอาร์เรย์ก่อน (จากน้อยไปหามากตามค่าเริ่มต้น) จากนั้นใช้np.flip () ( https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html )

FYI มันทำงานกับวัตถุวันที่และเวลาเช่นกัน

ตัวอย่าง:

    x = np.array([2,3,1,0]) 
    x_sort_asc=np.sort(x) 
    print(x_sort_asc)

    >>> array([0, 1, 2, 3])

    x_sort_desc=np.flip(x_sort_asc) 
    print(x_sort_desc)

    >>> array([3,2,1,0])

สำหรับผู้ที่มี NaN อยู่ในอาร์เรย์โปรดใช้ความระมัดระวังวิธีการต่างๆที่นำเสนอจะให้ผลลัพธ์ที่แตกต่างกัน ตัวอย่างเช่นถ้าวิธีx = np.array([2,3,np.nan,1,0]) นั้นให้np.flip(np.sort(x))ผล [nan 3 2. 1. 0. ] ในขณะที่-np.sort(-x)วิธีการให้ผลตอบแทน [3. 2. 1. 0. nan]
Uwe Mayer

1

นี่คือเคล็ดลับง่ายๆ

In[3]: import numpy as np
In[4]: temp = np.random.randint(1,10, 10)
In[5]: temp
Out[5]: array([5, 4, 2, 9, 2, 3, 4, 7, 5, 8])

In[6]: sorted = np.sort(temp)
In[7]: rsorted = list(reversed(sorted))
In[8]: sorted
Out[8]: array([2, 2, 3, 4, 4, 5, 5, 7, 8, 9])

In[9]: rsorted
Out[9]: [9, 8, 7, 5, 5, 4, 4, 3, 2, 2]

-3

ฉันขอแนะนำให้ใช้สิ่งนี้ ...

np.arange(start_index, end_index, intervals)[::-1]

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

np.arange(10, 20, 0.5)
np.arange(10, 20, 0.5)[::-1]

จากนั้น resault ของคุณ:

[ 19.5,  19. ,  18.5,  18. ,  17.5,  17. ,  16.5,  16. ,  15.5,
    15. ,  14.5,  14. ,  13.5,  13. ,  12.5,  12. ,  11.5,  11. ,
    10.5,  10. ]

1
วิธีนี้แก้ปัญหาได้อย่างไร? คุณเพียงแค่สร้างความสมบูรณ์ที่ไม่เกี่ยวข้องกันใหม่ (มากไปหาน้อย) อาร์เรย์ที่ - โดยวิธีการ - np.arange(20-0.5, 10-0.5, -0.5)สามารถทำได้ในวิธีที่มีประสิทธิภาพมากขึ้น: แต่นั่นเป็นเรื่องที่แตกต่างออกไปและอาจเป็นเพราะความสามารถในการอ่านที่แย่กว่าจึงเป็นที่ถกเถียงกัน อาร์เรย์อินพุตไม่ได้เรียงลำดับเลย
Daniel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.