Bagaimana cara mengubah daftar array numpy menjadi array numpy tunggal?

110

Misalkan saya punya;

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

Saya mencoba untuk mengubah;

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

Saya menyelesaikannya dengan iterasi di vstack sekarang tetapi sangat lambat untuk LIST yang sangat besar

Apa yang Anda sarankan untuk cara terbaik yang efisien?

erogol
sumber
5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]ini bukan sintaks python yang benar. Mohon klarifikasi.
Marcin

Jawaban:

140

Secara umum, Anda dapat menggabungkan seluruh urutan array di sepanjang sumbu:

numpy.concatenate( LIST, axis=0 )

tetapi Anda tidak harus khawatir tentang bentuk dan dimensi dari setiap array dalam daftar (untuk output 3x5 2-dimensi, Anda perlu untuk memastikan bahwa mereka semua 2-dimensi array n-by-5 sudah). Jika Anda ingin menggabungkan larik 1 dimensi sebagai baris dari keluaran 2 dimensi, Anda perlu memperluas dimensinya.

Seperti yang ditunjukkan oleh jawaban Jorge, ada juga fungsi yang stackdiperkenalkan di numpy 1.10:

numpy.stack( LIST, axis=0 )

Ini mengambil pendekatan komplementer: ini membuat tampilan baru dari setiap larik masukan dan menambahkan dimensi tambahan (dalam hal ini, di sebelah kiri, sehingga setiap nlarik -elemen 1D menjadi larik 1-kali- n2D) sebelum digabung. Ini hanya akan berfungsi jika semua larik masukan memiliki bentuk yang sama — bahkan di sepanjang sumbu penggabungan.

vstack(atau secara ekuivalen row_stack) sering kali merupakan solusi yang lebih mudah digunakan karena akan mengambil urutan array 1 dan / atau 2 dimensi dan memperluas dimensionalitas secara otomatis jika perlu dan hanya jika perlu, sebelum menggabungkan seluruh daftar bersama. Di mana dimensi baru diperlukan, itu ditambahkan di sebelah kiri. Sekali lagi, Anda dapat menggabungkan seluruh daftar sekaligus tanpa perlu mengulang:

numpy.vstack( LIST )

Perilaku fleksibel ini juga ditunjukkan oleh pintasan sintaksis numpy.r_[ array1, ...., arrayN ](perhatikan tanda kurung siku). Ini bagus untuk menggabungkan beberapa larik yang dinamai secara eksplisit tetapi tidak baik untuk situasi Anda karena sintaks ini tidak akan menerima urutan larik, seperti milik Anda LIST.

Ada juga fungsi column_stackdan pintasan analog c_[...], untuk penumpukan horizontal (berdasarkan kolom), serta fungsi yang hampir analog hstack— meskipun untuk beberapa alasan yang terakhir kurang fleksibel (lebih ketat tentang dimensi larik masukan, dan mencoba menggabungkan Array 1-D ujung ke ujung alih-alih memperlakukannya sebagai kolom).

Akhirnya, dalam kasus khusus penumpukan vertikal dari larik 1-D, berikut ini juga berfungsi:

numpy.array( LIST )

... karena array dapat dibuat dari urutan array lain, menambahkan dimensi baru ke awal.

jez
sumber
5
Saya pikir dia menginginkan array 2d sebagai output.
Beefster
8

Mulai dari NumPy versi 1.10, kami memiliki metode tumpukan . Itu dapat menumpuk array dari dimensi apa pun (semuanya sama):

# 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

Nikmati,

Jorge E. Cardona
sumber
1

Saya memeriksa beberapa metode untuk kinerja kecepatan dan menemukan bahwa tidak ada perbedaan! Satu-satunya perbedaan adalah bahwa menggunakan beberapa metode Anda harus memeriksa dimensi dengan cermat.

Waktu:

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

Seperti yang Anda lihat, saya mencoba 2 percobaan - menggunakan np.random.rand(10000)dan np.random.rand(1, 10000) Dan jika kita menggunakan array 2d daripada np.stackdan np.arraymembuat dimensi tambahan - result.shape adalah (1.100.000.100.000) dan (10.000.1.100.000) sehingga mereka membutuhkan tindakan tambahan untuk menghindari hal ini .

Kode:

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}')
Mikhail_Sam
sumber