numpy.vstackは、配列同士を縦に重ねる関数ですが、正確には、1次元配列同士を重ねる場合を除いて、numpy.concatenateで「最初の軸(axis=0)」で連結していくのと同じです。
実際のコードを見て確認していきましょう。
1. numpy.vstackの使い方
numpy.vstackの「v」は「vertical(垂直に)」の頭文字です。「stack」は「重ねる」という意味なので、vstackは「縦に重ねる」という意味になります。
それでは、基本的な書き方を確認しましょう。
書き方:
np.vstack(tup)
パラメーター:
引数 | 型 | 解説 |
tup | sequence of ndarrays | ここで指定した配列を重ねます。重ねる配列の組み合わせはリストかタプルで渡します。また配列同士は、最初の軸(axis=0)以外のshapeが一致している必要があります。1次元配列同士の場合は、列数(要素数)が揃っている必要があります。 |
戻り値:
要素を重ねた新しい最低2次元配列のndarray |
一緒に確認したい関数:
- stack: 配列を連結して次元数が1つ上の配列を生成
- hstack: 配列を水平に連結
- dstack: 配列を奥行き方向に連結
- concatenate: 配列を連結
- split
- block
numpy.vstackは、1次元配列同士を重ねる場合は、shape(N, )の1次元配列を一つずつshape(1, N)の2次元配列に変えて重ねていきます。
そして、shape(N, )の2つの1次元配列を重ねるとshape(2, N)の2次元配列になり、5つの1次元配列を重ねるとshape(5, N)の2次元配列になります。1次元配列同士を重ねる場合のみ、次元が1つあがって2次元配列になります。
なお、1次元配列を重ねる場合は、列数が揃っている必要があります。
2次元配列以上の場合は、numpy.concatenateで「axis=0」で連結していくのと同じことになります。2次元配列の場合、「axis=0」は行です。そのため行を重ねていきます。
例えば、shape(2, N)の2次元配列を2つ重ねるならshape(4, N)、3つ重ねるならshape(6, N)の2次元配列を生成します。shape(3, N)の2次元配列なら、2つ重ねるとshape(6, N)、3つ重ねるとshape(9, N)の2次元配列になります。
2次元配列を重ねる場合も、列数が揃っている必要があります。列数が同じであれば行数が異なっていても構いません。
次に3次元配列同士を重ねる場合です。3次元配列の場合、「axis=0」は奥行きです。そのため奥行きを重ねていきます。
つまり、shape(2, N, M)の3次元配列を、2つ重ねるとshape(4, N, M)、3つ重ねるとshape(6, N, M)の3次元配列を生成します。shape(3, N, M)の3次元配列なら2つ重ねた場合はshape(6, N, M)、3つ重ねた場合はshape(9, N, M)の3次元配列になります。
3次元配列同士を重ねる場合は、行数と列数が揃っている必要があります。行数と列数が揃っていれば、奥行き数が異なる3次元配列同士でも重ねることができます。
numpy.vstackは、3次元までの配列を扱うのに適しています。例えば、「高さ・幅・r/g/b」の3つの軸をもつピクセルデータのようなデータを扱うときによく使われます。
それでは実際に、numpy.vstackの使い方を見ていきましょう。
1.1. 1次元配列同士の場合は行を重ねた2次元配列を生成
まず1次元配列同士をnumpy.vstackで重ねてみましょう。この場合、上述のように、shape(N, )の1次元配列を一つずつshape(1, N)の2次元配列に変えて重ねた2次元配列を生成します。
そして、重ねる1次元配列の数に従って、shape(2, N)、shape(3, N)というように配列の数と同じ行数の2次元配列を生成します。
早速、以下のコードをご確認ください。shape(3,)の1次元配列を2つ重ねているので、shape(2, 3)の2次元配列が生成されています。
なおコード内で使用しているnp.arangeは『numpy.arange – 色々な連番の配列を生成』で解説しています。
import numpy as np
''' 1次元配列を重ねる。 '''
# 元の配列①を生成
arr1 = np.arange(3)
# 元の配列②を生成
arr2 = np.arange(3, 6)
# ①と②を重ねた新しい配列を生成
arr3 = np.vstack((arr1, arr2))
print('arr1: 元の配列①\n', arr1, '\n')
print('arr2: 元の配列②\n', arr2, '\n')
print('arr3: 新しい配列\n', arr3, '\n')
print('arr3のshape\n', arr3.shape, '\n')
print('arr3の次元数\n', arr3.ndim)
3つ以上の配列を重ねることもできます。
以下のコードでは、shape(3,)の1次元配列を3つ重ねているので、shape(3, 3)の2次元配列が生成されています。
''' 3つ以上の配列を重ねることもできます。 '''
# 元の配列③を生成
arr4 = np.arange(6, 9)
# ①と②と③を重ねた新しい配列を生成
arr5 = np.vstack((arr1, arr2, arr4))
print('arr5\n', arr5, '\n')
print('arr5のshape\n', arr5.shape, '\n')
print('arr5の次元数\n', arr5.ndim)
それぞれの1次元配列の列数が異なっている場合はエラーになります。以下のコードでは、shape(3,)とshape(4,)の列数が異なる1次元配列を重ねようとしているので、エラーになっています。
''' 配列の列数が異なるとエラー。'''
# 4列(要素数4)の1次元配列④を生成
arr6 = np.arange(4)
print('arr1: 元の配列①\n', arr1, '\n')
print('arr6: 元の配列④\n', arr6, '\n')
# 3列と4列の配列を重ねようとするとエラー
np.vstack((arr1, arr6))
1次元配列を重ねた場合は、戻り値は2次元配列になる点を、あらためておさえておきましょう。
1.2. 2次元配列同士の場合は行を重ねる
続いて2次元配列同士の場合を見てみましょう。
2次元配列では「axis=0」は行です。
そのため、shape(2, N)の2次元配列を2つ重ねるならshape(4, N)、3つ重ねるならshape(6, N)の2次元配列を生成します。shape(3, N)の2次元配列なら、2つ重ねるとshape(6, N)、3つ重ねるとshape(9, N)の2次元配列になります。
2次元配列を重ねる場合も、列数が揃っている必要があります。列数が同じであれば行数が異なる2次元配列同士を重ねることができます。
その場合は、例えば、shape(2, N)とshape(3, N)の2次元配列を重ねると、shape(5, 3)の2次元配列が生成されます。
この場合、np.stack()と異なり、2次元配列同士を重ねても3次元配列にはなりません。行数だけが増えていきます。
さて、以下のコードでご確認ください。shape(2, 3)の2次元配列を2つ重ねているので、shape(4, 3)の2次元配列が生成されます。
なお、コード内で使用しているreshape()は『NumPyのreshapeで配列を形状変換する方法』で解説しています。
''' 2次元配列でも行を重ねる。 '''
# 元の2次元配列①を生成
arr7 = np.arange(6).reshape(2, 3)
# 元の2次元配列②を生成
arr8 = np.arange(6, 12).reshape(2, 3)
# ①と②を重ねた新しい配列を生成
arr9 = np.vstack((arr7, arr8))
print('arr7: 元の2次元配列①\n', arr7, '\n')
print('arr8: 元の2次元配列②\n', arr8, '\n')
print('arr9: 新しい配列\n', arr9, '\n')
print('arr9のshape\n', arr9.shape, '\n')
print('arr9の次元数\n', arr9.ndim)
なお、2次元配列の場合は、配列の列数が揃っていれば、行数に関係なく重ねることが可能です。
以下のコードで確認しましょう。shape(2, 3)とshape(3, 3)の行数が異なる2次元配列を重ねているので、shape(5, 3)の2次元配列が生成されています。
''' 2次元配列の場合は列数が合っていればOK '''
# 2次元配列③を生成
arr10 = np.arange(6, 15).reshape(3, 3)
# 2次元配列①と③を重ねる
arr11 = np.vstack((arr7, arr10))
print('arr7: 元の2次元配列①\n', arr7, '\n')
print('arr10: 元の2次元配列③\n', arr10, '\n')
print('arr11: 新しい配列\n', arr11)
しかし、列数が揃っていない場合はエラーになります。以下のコードでは、shape(2, 3)とshape(3, 2)の列数の異なる配列を重ねようとしているのでエラーになっています。
''' 列数が異なる2次元配列同士ではエラー '''
# 2次元配列④を生成
arr12 = np.arange(6, 12).reshape(3, 2)
print('arr7: 元の2次元配列①\n', arr7, '\n')
print('arr12: 元の2次元配列④\n', arr12, '\n')
# 2次元配列①と④は列数が異なるので重ねるとエラー
np.vstack((arr7, arr12))
2次元配列同士の場合は、行を重ねた2次元配列を生成するという点をおさえておきましょう。
1.3. 3次元配列同士の場合は奥行きを重ねる
次に3次元配列同士の場合を見ていきましょう。
3次元配列の「axis=0」は奥行きです。そのため奥行きが増加していきます。
例えば、shape(2, N, M)の3次元配列を、2つ重ねるとshape(4, N, M)、3つ重ねるとshape(6, N, M)の3次元配列を生成します。shape(3, N, M)の3次元配列なら2つ重ねた場合はshape(6, N, M)、3つ重ねた場合はshape(9, N, M)の3次元配列になります。
3次元配列の場合は、配列の行数と列数が揃っていれば、奥行きが異なる配列同士を重ねることができます。
その場合、例えば、shape(2, N, M)の配列とshape(4, N, M)の配列を重ねると、shape(6, N, M)の配列になります。
それでは、まず以下のコードをご確認ください。shape(2, 2, 3)の3次元配列を2つ重ねているので、shape(4, 2, 3)の配列が生成されています。
''' 3次元配列以上では奥行きを重ねる。 '''
# 3次元配列①を生成
arr13 = np.arange(12).reshape(2, 2, 3)
# 3次元配列②を生成
arr14 = np.arange(12, 24).reshape(2, 2, 3)
# ①と②の行を重ねる
arr15 = np.vstack((arr13, arr14))
print('arr13: 元の3次元配列①\n', arr13, '\n')
print('arr14: 元の3次元配列②\n', arr14, '\n')
print('arr15: 新しい配列\n', arr15, '\n')
print('arr15のshape\n', arr15.shape, '\n')
print('arr15の次元数\n', arr15.ndim)
3次元配列同士を重ねる場合は、奥行き数に関わらず、行数と列数が揃っていればOKです。以下のコードは、shape(2, 2, 3)とshape(3, 2, 3)の奥行きが異なり、行数と列数が揃っている配列を重ねて、shape(5, 2, 3)の配列を生成しています。
''' 3次元配列の場合は、行数と列数が揃っていればOK。 '''
# 3次元配列③を生成
arr16 = np.arange(12, 30).reshape(3, 2, 3)
# 3次元配列①と③を重ねる
arr17 = np.vstack((arr13, arr16))
print('arr13: 元の3次元配列①\n', arr13, '\n')
print('arr16: 元の3次元配列②\n', arr16, '\n')
print('arr17: 新しい配列\n', arr17, '\n')
print('arr17のshape\n', arr17.shape, '\n')
print('arr17の次元数\n', arr17.ndim)
ただし、行数と列数のいずれか一方でも揃っていなければ、以下のようにエラーになります。
''' 行数や列数が揃っていなければエラーになります。 '''
# 3次元配列④を生成
arr18 = np.arange(12, 20).reshape(2, 1, 4)
print('arr13: 元の3次元配列①\n', arr13, '\n')
print('arr18: 元の3次元配列④\n', arr18, '\n')
# 配列①と④は行数や列数が揃っていないのでエラー
np.vstack((arr13, arr18))
このように、3次元配列同士をnumpy.vstackで重ねる場合は、奥行きとして重なっていくことをおさえておきましょう。
2. まとめ
numpy.vstackの使い方は以上の通りです。同じような関数として、以下も確認しておくと良いでしょう。
コメント