Làm thế nào để chuyển đổi danh sách các mảng numpy thành một mảng numpy?


103

Giả sử tôi có;

LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])] # inner lists are numpy arrays

Tôi cố gắng chuyển đổi;

array([[1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5])

Tôi đang giải quyết nó bằng cách lặp lại trên vstack ngay bây giờ nhưng nó thực sự chậm đối với LIST đặc biệt lớn

Bạn đề xuất gì cho cách hiệu quả nhất?


5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]đây không phải là cú pháp python chính xác. Vui lòng làm rõ.
Marcin

Câu trả lời:


131

Nói chung, bạn có thể nối một chuỗi toàn bộ mảng dọc theo bất kỳ trục nào:

numpy.concatenate( LIST, axis=0 )

nhưng bạn làm phải lo lắng về hình dáng và chiều của mỗi mảng trong danh sách (đối với một sản lượng 3x5 2 chiều, bạn cần phải đảm bảo rằng họ là tất cả 2 chiều n-by-5 mảng đã được). Nếu bạn muốn nối các mảng 1 chiều như các hàng của đầu ra 2 chiều, bạn cần mở rộng kích thước của chúng.

Như câu trả lời của Jorge đã chỉ ra, cũng có chức năng stack, được giới thiệu trong numpy 1.10:

numpy.stack( LIST, axis=0 )

Điều này sử dụng phương pháp bổ sung: nó tạo ra một dạng xem mới của mỗi mảng đầu vào và thêm một thứ nguyên bổ sung (trong trường hợp này là ở bên trái, vì vậy mỗi nmảng -tăng số 1D trở thành một mảng 1 x n2D) trước khi nối. Nó sẽ chỉ hoạt động nếu tất cả các mảng đầu vào có cùng hình dạng — thậm chí dọc theo trục nối.

vstack(hoặc tương đương row_stack) thường là một giải pháp dễ sử dụng hơn vì nó sẽ lấy một chuỗi các mảng 1 và / hoặc 2 chiều và tự động mở rộng kích thước khi cần thiết và chỉ khi cần thiết, trước khi nối toàn bộ danh sách với nhau. Khi yêu cầu thứ nguyên mới, thứ nguyên này sẽ được thêm vào bên trái. Một lần nữa, bạn có thể nối toàn bộ danh sách cùng một lúc mà không cần lặp lại:

numpy.vstack( LIST )

Hành vi linh hoạt này cũng được thể hiện bằng phím tắt cú pháp numpy.r_[ array1, ...., arrayN ](lưu ý dấu ngoặc vuông). Điều này tốt cho việc nối một vài mảng được đặt tên rõ ràng nhưng không tốt cho tình huống của bạn vì cú pháp này sẽ không chấp nhận một chuỗi các mảng, giống như của bạn LIST.

Ngoài ra còn có một hàm column_stackvà phím tắt tương tự c_[...], để xếp chồng theo chiều ngang (theo cột), cũng như một hàm gần như -analogous hstack— mặc dù vì một số lý do, hàm sau kém linh hoạt hơn (nó chặt chẽ hơn về kích thước của mảng đầu vào và cố gắng nối Các mảng 1-D end-to-end thay vì coi chúng là cột).

Cuối cùng, trong trường hợp cụ thể của việc xếp chồng theo chiều dọc của mảng 1-D, điều sau cũng hoạt động:

numpy.array( LIST )

... bởi vì mảng có thể được xây dựng từ một chuỗi các mảng khác, thêm một chiều mới vào đầu.


5
Tôi nghĩ anh ấy muốn một mảng 2d làm đầu ra.
Beefster

7

Bắt đầu từ phiên bản NumPy 1.10, chúng ta có ngăn xếp phương thức . Nó có thể xếp chồng các mảng có kích thước bất kỳ (tất cả đều bằng nhau):

# List of arrays.
L = [np.random.randn(5,4,2,5,1,2) for i in range(10)]

# Stack them using axis=0.
M = np.stack(L)
M.shape # == (10,5,4,2,5,1,2)
np.all(M == L) # == True

M = np.stack(L, axis=1)
M.shape # == (5,10,4,2,5,1,2)
np.all(M == L) # == False (Don't Panic)

# This are all true    
np.all(M[:,0,:] == L[0]) # == True
all(np.all(M[:,i,:] == L[i]) for i in range(10)) # == True

Thưởng thức,


1

Tôi đã kiểm tra một số phương pháp cho hiệu suất tốc độ và thấy rằng không có sự khác biệt! Sự khác biệt duy nhất là sử dụng một số phương pháp, bạn phải kiểm tra kích thước cẩn thận.

Thời gian:

|------------|----------------|-------------------|
|            | shape (10000)  |  shape (1,10000)  |
|------------|----------------|-------------------|
| np.concat  |    0.18280     |      0.17960      |
|------------|----------------|-------------------|
|  np.stack  |    0.21501     |      0.16465      |
|------------|----------------|-------------------|
| np.vstack  |    0.21501     |      0.17181      |
|------------|----------------|-------------------|
|  np.array  |    0.21656     |      0.16833      |
|------------|----------------|-------------------|

Như bạn có thể thấy, tôi đã thử 2 thử nghiệm - sử dụng np.random.rand(10000)np.random.rand(1, 10000) Và nếu chúng tôi sử dụng mảng 2d hơn np.stacknp.arraytạo thêm thứ nguyên - kết quả. Hình dạng là (1.10000.100) và (10000.1.100), vì vậy chúng cần các hành động bổ sung để tránh điều này .

Mã:

from time import perf_counter
from tqdm import tqdm_notebook
import numpy as np
l = []
for i in tqdm_notebook(range(10000)):
    new_np = np.random.rand(10000)
    l.append(new_np)



start = perf_counter()
stack = np.stack(l, axis=0 )
print(f'np.stack: {perf_counter() - start:.5f}')

start = perf_counter()
vstack = np.vstack(l)
print(f'np.vstack: {perf_counter() - start:.5f}')

start = perf_counter()
wrap = np.array(l)
print(f'np.array: {perf_counter() - start:.5f}')

start = perf_counter()
l = [el.reshape(1,-1) for el in l]
conc = np.concatenate(l, axis=0 )
print(f'np.concatenate: {perf_counter() - start:.5f}')
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.