2011-07-21 39 views
174

Tin hay không, sau khi lược tả mã hiện tại của tôi, hoạt động lặp đi lặp lại của sự đảo ngược mảng numpy ăn một đoạn khổng lồ của thời gian chạy. Những gì tôi có ngay bây giờ là phổ biến phương pháp xem dựa trên:Cách hiệu quả nhất để đảo ngược một mảng numpy

reversed_arr = arr[::-1] 

Có cách nào khác để làm điều đó một cách hiệu quả hơn, hoặc là nó chỉ là một ảo tưởng từ nỗi ám ảnh của tôi với hiệu suất NumPy không thực tế?

+10

Er ... 'arr [:: - 1]' vừa trả về chế độ xem được đảo ngược. Nó nhanh như bạn có thể nhận được, và không phụ thuộc vào số lượng các mục trong mảng, vì nó chỉ thay đổi các bước tiến. Là những gì bạn đang thực sự đảo ngược một mảng numpy? –

+0

vâng, thực sự, 'arr' là một mảng numpy. – nye17

+10

Hmmm ... Vâng, trên máy tính xách tay của tôi phải mất khoảng 670 nano giây bất kể độ dài của mảng. Nếu đó là nút cổ chai của bạn, bạn có thể cần phải chuyển đổi ngôn ngữ ... Tôi khá chắc chắn bạn sẽ không tìm thấy một cách nhanh hơn để đảo ngược một mảng numpy. Chúc may mắn, ở mức nào! –

Trả lời

148

Khi bạn tạo reversed_arr bạn đang tạo chế độ xem vào mảng ban đầu. Sau đó bạn có thể thay đổi mảng ban đầu và chế độ xem sẽ cập nhật để phản ánh các thay đổi.

Bạn có đang tạo lại chế độ xem thường xuyên hơn mức bạn cần không? Bạn sẽ có thể làm điều gì đó như thế này:

arr = np.array(some_sequence) 
reversed_arr = arr[::-1] 

do_something(arr) 
look_at(reversed_arr) 
do_something_else(arr) 
look_at(reversed_arr) 

Tôi không phải là chuyên gia vất vả, nhưng điều này có vẻ như đó là cách nhanh nhất để làm những việc khó khăn. Nếu đây là những gì bạn đã làm, tôi không nghĩ rằng bạn có thể cải thiện nó.

P.S. Lớn thảo luận về quan điểm NumPy đây:

View onto a numpy array?

+0

Liệu nó có giúp tạo một đối tượng slice và sau đó tái sử dụng nó trên nhiều mảng không? – endolith

+1

Thực ra tôi đã thử nghiệm nó và không thấy bất kỳ sự khác biệt nào với đối tượng slice được tạo bên ngoài vòng lặp. (Oh đợi đã, nó nhanh hơn một chút. Lặp lại 43,4 ms so với 44,3 ms cho vòng lặp 1000000) – endolith

29

np.fliplr() flips mảng trái sang phải.

Lưu ý rằng đối với mảng 1d, bạn cần phải đánh lừa nó một chút:

arr1d = np.array(some_sequence) 
reversed_arr = np.fliplr([arr1d])[0] 
+23

'reversed_arr = np.flipud (arr1d)' dường như hoạt động trực tiếp. –

+0

@ThomasArildsen - thú vị. Cảm ơn – KolaB

3

tôi sẽ mở rộng trên câu trả lời trước đó về np.fliplr(). Dưới đây là một số mã thể hiện việc xây dựng một mảng 1d, chuyển đổi nó thành một mảng 2d, lật nó, sau đó chuyển đổi trở lại thành mảng 1d. time.clock() sẽ được sử dụng để giữ thời gian, được trình bày theo số giây.

import time 
import numpy as np 

start = time.clock() 
x = np.array(range(3)) 
#transform to 2d 
x = np.atleast_2d(x) 
#flip array 
x = np.fliplr(x) 
#take first (and only) element 
x = x[0] 
#print x 
end = time.clock() 
print end-start 

Với tuyên bố in không chú thích:

[2 1 0] 
0.00203907123594 

Với tuyên bố in ra nhận xét:

5.59799927506e-05 

Vì vậy, về mặt hiệu quả, tôi nghĩ đó là phong nha. Đối với những người bạn yêu thích để làm điều đó trong một dòng, đây là hình thức đó.

np.fliplr(np.atleast_2d(np.array(range(3))))[0] 
+3

Điều gì đó với một mảng nhỏ như vậy là khá vô ích. Nếu bạn muốn so sánh mọi thứ, tốt nhất là nên sử dụng thứ gì đó mất một khoảng thời gian, như 3000 hoặc thậm chí là nhiều yếu tố khác. – Barabas

22

Bởi vì điều này dường như không được đánh dấu là đã trả lời chưa ... Câu trả lời của Thomas Arildsen nên là thích hợp nhất: chỉ cần sử dụng

np.flipud(your_array) 

nếu nó là một mảng 1d (cột mảng) .

Với matrizes làm

fliplr(matrix) 

nếu bạn muốn đảo ngược dòng và flipud(matrix) nếu bạn muốn lật cột. Không cần phải tạo mảng 1d của bạn một mảng hàng 2 chiều (ma trận với một lớp Không có) và sau đó lật nó.

0

Để có nó làm việc với các số âm và một danh sách dài bạn có thể làm như sau:

b = numpy.flipud(numpy.array(a.split(),float)) 

đâu flipud là dành cho ARRA 1d

14

Như đã đề cập ở trên, a[::-1] thực sự chỉ tạo ra một cái nhìn , do đó, nó là một hoạt động liên tục thời gian (và như vậy không mất nhiều thời gian như mảng phát triển). Nếu bạn cần mảng được tiếp giáp (ví dụ bởi vì bạn đang thực hiện nhiều hoạt động vector với nó), ascontiguousarray là về càng nhanh càng flipup/fliplr:

enter image description here


Mã để tạo ra những âm mưu :

import numpy 
import perfplot 


perfplot.show(
    setup=lambda n: numpy.random.randint(0, 1000, n), 
    kernels=[ 
     lambda a: a[::-1], 
     lambda a: numpy.ascontiguousarray(a[::-1]), 
     lambda a: numpy.fliplr([a])[0] 
     ], 
    labels=['a[::-1]', 'ascontiguousarray(a[::-1])', 'fliplr'], 
    n_range=[2**k for k in range(20)], 
    xlabel='len(a)', 
    logx=True, 
    logy=True, 
    ) 
Các vấn đề liên quan