2010-04-14 25 views
19

Thông thường, tôi đang xây dựng một mảng bằng cách duyệt qua một số dữ liệu, ví dụ .:Xây dựng một mảng trong numpy/scipy bằng cách lặp lại trong Python?

my_array = [] 
for n in range(1000): 
    # do operation, get value 
    my_array.append(value) 
# cast to array 
my_array = array(my_array) 

tôi thấy rằng tôi phải đầu tiên xây dựng một danh sách và sau đó cast nó (sử dụng "mảng") vào một mảng. Có cách nào xung quanh chúng không? Tất cả các cuộc gọi đúc lộn xộn mã ... làm thế nào tôi có thể lặp lại xây dựng "my_array", với nó là một mảng từ đầu?

+0

những gì xảy ra nếu bạn không làm điều đó? – OscarRyz

+2

Lý do không rõ ràng là nhanh như vậy ở nơi đầu tiên là nó hoạt động với mảng kích thước không đổi và không phải danh sách động. Vì vậy, loại bỏ nó chỉ để giảm "lộn xộn" trong mã của bạn có lẽ không đúng cách để đi. Nếu bạn biết kích thước trước (1000) hãy preallocate nó. Nếu bạn không - xây dựng danh sách chắc chắn là cách tốt nhất để đi, vì danh sách python [] khá hiệu quả. – drozzy

Trả lời

-2

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, điều này sẽ làm những gì bạn muốn:

# the array passed into your function 
ax = NP.random.randint(10, 99, 20).reshape(5, 4) 

# just define a function to operate on some data 
fnx = lambda x : NP.sum(x)**2 

# apply the function directly to the numpy array 
new_row = NP.apply_along_axis(func1d=fnx, axis=0, arr=ax) 

# 'append' the new values to the original array 
new_row = new_row.reshape(1,4) 
ax = NP.vstack((ax, new_row)) 
+4

Vì đây là câu trả lời được chấp nhận, tôi phải nói điều này: Tôi đã thấy vstack được sử dụng rất nhiều như thế này. Người ta phải biết rằng điều này thực sự (!) Không thực hiện. Nếu bạn xây dựng một mảng lớn theo cách này, bạn thực hiện rất nhiều thao tác sao chép bộ nhớ không cần thiết. xem câu trả lời dưới đây – xaedes

15

Cách khuyến khích để làm điều này là để preallocate trước khi vòng lặp và sử dụng cắt và lập chỉ mục để chèn

my_array = numpy.zeros(1,1000) 
for i in xrange(1000): 
    #for 1D array 
    my_array[i] = functionToGetValue(i) 
    #OR to fill an entire row 
    my_array[i:] = functionToGetValue(i) 
    #or to fill an entire column 
    my_array[:,i] = functionToGetValue(i) 

NumPy không cung cấp một phương pháp array.resize(), nhưng điều này sẽ xa chậm hơn do chi phí tái phân bổ bộ nhớ bên trong một vòng lặp. Nếu bạn phải có tính linh hoạt, thì tôi e rằng cách duy nhất là tạo một array từ một số list.

EDIT: Nếu bạn lo lắng rằng bạn đang phân bổ quá nhiều bộ nhớ cho dữ liệu của mình, tôi sẽ sử dụng phương pháp trên để phân bổ quá mức và sau đó khi vòng lặp hoàn tất, hãy xóa các bit không sử dụng của mảng array.resize(). Đây sẽ là xa, xa nhanh hơn liên tục phân bổ lại mảng bên trong vòng lặp.

EDIT: Đáp lại bình luận @ user248237 của, giả sử bạn biết bất kỳ một kích thước của mảng (để đơn giản):

my_array = numpy.array(10000, SOMECONSTANT) 

for i in xrange(someVariable): 
    if i >= my_array.shape[0]: 
     my_array.resize((my_array.shape[0]*2, SOMECONSTANT)) 

    my_array[i:] = someFunction() 

#lop off extra bits with resize() here 

Nguyên tắc chung là "phân bổ nhiều hơn bạn nghĩ rằng bạn sẽ cần, và nếu mọi thứ thay đổi, hãy thay đổi kích cỡ mảng càng ít lần càng tốt ". Tăng gấp đôi kích thước có thể được coi là quá mức, nhưng trên thực tế, đây là phương pháp được sử dụng bởi một số cấu trúc dữ liệu trong một số thư viện chuẩn trong các ngôn ngữ khác (ví dụ: java.util.Vector).).

+2

Nếu tôi không biết kích thước trước thời hạn thì sao? – user248237dfsf

+0

Điều đó có ý nghĩa, nhưng giả sử tôi xây dựng các mảng theo cách này bằng cách phân bổ nhiều hơn tôi cần - làm thế nào tôi có thể lặp lại qua mảng? Nếu tôi phân bổ numpy.zeros (1, 1000) nhưng chỉ sử dụng 50 phần tử, tôi không muốn lặp lại cho đến khi tôi đạt đến số không ... cách tiếp cận tổng thể dường như tạo ra tình huống kỳ lạ này, trong đó mỗi kiểu dữ liệu mảng sẽ yêu cầu điều kiện "dừng" khác nhau cho vòng lặp. Có cách nào để giái quyết vấn đề này không? – user248237dfsf

+0

Như tôi đã nói, bạn có thể thực hiện cuộc gọi cuối cùng để 'thay đổi kích thước()' khi vòng lặp được thực hiện. Nếu bạn thu nhỏ mảng thành kích thước chính xác, bạn sẽ vứt bỏ tất cả các phần tử zero. –

29

NumPy cung cấp một phương pháp 'fromiter':

def myfunc(n): 
    for i in range(n): 
     yield i**2 


np.fromiter(myfunc(5), dtype=int) 

trong đó sản lượng

array([ 0, 1, 4, 9, 16]) 
+1

Khi sử dụng 'np.fromiter' và bạn biết kích thước của mảng trước, bạn có thể chuyển nó thành tham số để mảng được phân bổ trước. Điều này làm tăng hiệu suất vô cùng. Vì vậy, trong ví dụ trên, hãy làm: 'np.fromiter (myfunc (5), dtype = int, count = 5)' –

Các vấn đề liên quan