numpy配列のリストを単一のnumpy配列に変換するにはどうすればよいですか?


100

私が持っていると仮定します。

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

私は変換しようとします。

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

私は今、vstackの反復によってそれを解決していますが、特に大きなLISTの場合は本当に遅いです

最も効率的な方法として何を提案しますか?


5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]これは正しいpython構文ではありません。どうか明らかにしてください。
Marcin、2014

回答:


128

一般に、任意の軸に沿って配列のシーケンス全体を連結できます。

numpy.concatenate( LIST, axis=0 )

しかし、あなたはない、リスト内の各配列(2次元は3x5出力のために、あなたは、彼らはすでに、すべての2次元のn-によって-5アレイであることを確認する必要がある)の形状と次元を心配する必要があります。1次元配列を2次元出力の行として連結する場合は、それらの次元を拡張する必要があります。

ホルヘの答えが指摘するように、stacknumpy 1.10で導入された関数もあります:

numpy.stack( LIST, axis=0 )

これは、補完的なアプローチを取ります。連結する前に、各入力配列の新しいビューを作成し、追加の次元(この場合は左側にあるため、各n要素1D配列は1行n2D配列になります)を追加します。すべての入力配列が同じ形状(連結軸に沿っていても)である場合にのみ機能します。

vstack(または同等のrow_stack)は、1次元または2次元配列のシーケンスを取得し、リスト全体を連結する前に、必要な場合にのみ、必要な場合にのみ次元を自動的に拡張するため、より使いやすいソリューションです。新しいディメンションが必要な場合は、左側に追加されます。繰り返しますが、繰り返しを行う必要なく、リスト全体を一度に連結できます。

numpy.vstack( LIST )

この柔軟な動作は、構文のショートカットでも示されnumpy.r_[ array1, ...., arrayN ]ます(角括弧に注意してください)。これは、明示的に名前が付けられたいくつかの配列を連結するのに適していますが、この構文はのような配列のシーケンスを受け入れないため、状況に適していませんLIST

水平(列方向)スタッキング用の類似の関数column_stackとショートカットc_[...]、およびほぼ類似の関数もあります。hstackただし、何らかの理由で後者は柔軟性が低くなります(入力配列の次元については厳格であり、連結を試みます) 1次元配列は、列として扱うのではなく、エンドツーエンドです)。

最後に、1次元配列の垂直スタッキングの特定のケースでは、以下も機能します。

numpy.array( LIST )

...配列は他の配列のシーケンスから構築でき、新しい次元を最初に追加するためです。


5
彼は出力として2D配列が欲しかったと思います。
Beefster 2017年

7

NumPyバージョン1.10以降、メソッドstackがあります。任意の次元(すべて等しい)の配列をスタックできます。

# 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

楽しい、


1

いくつかの方法でスピードパフォーマンスを確認したところ、違いはありませんでした。 唯一の違いは、いくつかの方法を使用して、寸法を注意深くチェックする必要があることです。

タイミング:

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

あなたが見ることができるように、私は2つの実験を試しました-を使用しnp.random.rand(10000)np.random.rand(1, 10000) そして2D配列を使用np.stacknp.arrayて追加の次元を作成する場合-結果。形状は(1,10000,10000)と(10000,1,10000)なので、これを回避するには追加のアクションが必要です。

コード:

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}')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.