numpy.concatenateは、配列同士を連結して新しい配列を生成する関数です。行や列のどちらを軸として連結するのかを、axis=によって指定する必要があります。
ここで、実際のコードを見ながら、使い方を確認していきましょう。
1. numpy.concatenateの使い方
まずは基本的な書き方を確認しましょう。
書き方:
np.concatenate((a1, a2,...), axis=0, out=None)
パラメーター:
引数 | 型 | 解説 |
a1, a2, … | array_like | ここに指定した配列を連結します。タプル型かリスト型で指定します。連結する配列は、指定したaxis以外が同じ形状(shape)である必要があります。 |
axis(optional) | int | 配列を結合する軸を指定します。Noneを指定した場合、戻り値の配列は1次元になります。デフォルト値は0です。 |
out(optional) | ndarray | np.concatenate()は、基本的には指定の配列を連結した新しい配列を生成します。しかし、この引数を指定することで、連結した配列で既存のリストを上書きすることができます。 |
戻り値:
要素を連結した新しいndarray |
一緒に確認したい関数:
それでは、実際のコードで一通り確認していきましょう。
1.1. 1次元配列同士の連結
まずは、1次元配列同士の連結を見ていきましょう。
注意点として、連結する配列はタプルかリストで渡す点を確認しましょう。また配列は3つ以上でも、好きなだけ連結することができます。
import numpy as np
# 元の配列①
arr1 = np.arange(4)
# 元の配列②
arr2 = np.arange(4, 6)
# 元の配列③
arr3 = np.arange(7, 11)
# 配列を連結(引数はタプルかリストで渡す)。
arr4 = np.concatenate((arr1, arr2))
# 3つの配列を連結。
arr5 = np.concatenate((arr1, arr2, arr3))
print('arr1: 元の配列①\n', arr1, '\n')
print('arr2: 元の配列②\n', arr2, '\n')
print('arr3: 元の配列③\n', arr3, '\n')
print('arr4: 新しい配列\n', arr4, '\n')
print('arr5: 3つの配列を連結した新しい配列\n', arr5, '\n')
元の配列に連結するのではなく、要素を連結した新しい配列を生成する点をおさえておきましょう。
tips: オプション引数「out=」で既存の配列を変更
もし、np.concatenate()で連結した配列で、既存の配列を変更したい場合はオプション引数「out=」を使います。
以下のコードでは、初期化した配列arr6を生成し、それをarr1とarr2の連結結果に変更するように指定しています。
# 新しい配列を生成
arr6 = np.zeros(6, int)
print('関数実行前のarr6\n', arr6, '\n')
# arr1とarr2を連結した配列をarr6に代入
np.concatenate((arr1, arr2), out=arr6)
print('関数実行後のarr6\n', arr6)
ただし、連結した配列のshapeとout=で指定した配列のshapeが異なる場合、または要素の型(dtype)が異なる場合はエラーになります。shapeやdtypeは『NumPyのarray(配列)の基本的操作まとめ』で解説しています。
''' 連結した配列とout=で指定した配列のshapeや型(dtype)が異なるとエラー '''
# 1×3の配列を生成
arr7 = np.arange(3)
# arr7とarr1+arr2はshapeが異なるためエラーになる。
np.concatenate((arr1, arr2), out=arr7)
なお、「out=」の使い方は2次元配列以上でも同じです。あまり頻繁に使うのではないので、以降の解説では割愛します。
1.2. 2次元配列同士の連結
続いて2次元配列同士の連結を見ていきましょう。
この場合、オプション引数「axis=」の指定によって連結結果が異なります。一つずつ確認していきましょう。
1.2.1. axis=0(デフォルト値)の場合は行を軸として連結
axis=を指定しない場合、デフォルトの「axis=0」を軸として連結します。2次元配列の場合は、「axis=0」は行なので行同士の連結になります。
そのため、例えば、shape(N, a)の2次元配列を2つ連結すればshape(2N, a)、3つ連結すればshape(3N, a)になります。
また、指定したaxis以外の要素が揃っている必要があるので、この場合はaxis=0(行)以外の要素、つまり列は揃っている必要があります。
実際に以下のコードで確認しましょう。全てshape(2, 3)の2次元配列同士の連結です。2つの連結でshape(4, 3)、2つの連結でshape(6, 3)の2次元配列になります。
# 元の配列①
arr8 = np.arange(6).reshape(2, 3)
# 元の配列②
arr9 = np.arange(6, 12). reshape(2, 3)
# 元の配列③
arr10 = np.arange(12, 18).reshape(2, 3)
# 2つの配列を連結
arr11 = np.concatenate((arr8, arr9))
# 3つの配列を連結
arr12 = np.concatenate((arr8, arr9, arr10))
print('arr8: 元の配列①\n', arr8, '\n')
print('arr9: 元の配列②\n', arr9, '\n')
print('arr10: 元の配列③\n', arr10, '\n')
print('arr11: 2つの配列を連結 np.concatenate((arr6, arr7))\n', arr11, '\n')
print('arr12: 3つの配列を連結 np.concatenate((arr6, arr7, arr8))\n', arr12)
デフォルト(axis=0)の場合、連結する配列の一行ごとの要素数が揃っていれば連結可能です。
以下のコードでは、shape(2, 3)とshape(1, 3)の配列の連結です。行数は異なりますが、列数は揃っているので連結が実行され、shape(3, 3)の2次元配列になっています。
''' 行数が異なっても一行ごとの要素数が同じなら連結可能 '''
# 元の配列④(1×3)
arr13 = np.arange(6, 9).reshape(1, 3)
# arr8とarr13を連結
arr14 = np.concatenate((arr8, arr13))
print('arr8: 元の配列①(2×3)\n', arr8, '\n')
print('arr13: 元の配列④(1×3)\n', arr13, '\n')
print('arr14: 新しい配列 np.concatenate((arr8, arr13))\n', arr14)
ただし、列数が揃っていない配列を連結しようとするとエラーになります。
''' 一行ごとの要素数が異なっていればエラー '''
# 元の配列⑤(1×4)
arr15 = np.arange(9, 13).reshape(1, 4)
print('arr8: 元の配列①(2×3)\n', arr8, '\n')
print('arr15: 元の配列④(1×4)\n', arr15, '\n')
# arr8とarr15は要素数が異なるので連結できない
np.concatenate((arr8, arr15))
なお、これは2次元配列同士で、numpy.vstackを実行しているのと同じことになります。3次元配列までの場合は、そちらを使うことが多いので、以下のページで確認しておきましょう。
1.2.2. axis=1で列を軸として連結
2次元配列では、「axis=1」は列です。そのため、これを指定した場合、列を軸として連結します。
例えば、shape(a, N)の2次元配列を2つ連結するとshape(a, 2N)、3つ連結するとshape(a, 3N)の2次元配列になります。
また、指定したaxis以外の要素は揃っている必要があるので、この場合はaxis=1(列)以外の要素である行数が揃っている必要があります。
以下のコードをご確認ください。shape(2, 2)の配列を2つ連結したらshape(2, 4)に、3つ連結したらshape(2, 6)の配列になっています。
# 元の配列①
arr16 = np.arange(4).reshape(2, 2)
# 元の配列②
arr17 = np.arange(4, 8).reshape(2, 2)
# 元の配列③
arr18 = np.arange(8, 12).reshape(2, 2)
# 2つの配列を連結
arr19 = np.concatenate((arr16, arr17), axis=1)
# 3つの配列を連結
arr20 = np.concatenate((arr16, arr17, arr18), axis=1)
print('arr16: 元の配列①\n', arr16, '\n')
print('arr17: 元の配列②\n', arr17, '\n')
print('arr18: 元の配列③\n', arr18, '\n')
print('arr19: 2つの配列を連結 np.concatenate((arr16, arr17), axis=1)\n', arr19, '\n')
print('arr20: 3つの配列を連結 np.concatenate((arr16, arr17, arr18), axis=1)\n', arr20)
この場合、連結する配列同士の行数が揃っていれば連結可能です。
''' shapeが異なっても行数が同じなら連結可能 '''
# 元の配列④(2×1)
arr21 = np.arange(13, 15).reshape(2, 1)
# arr16とarr21をaxis=1で連結
arr22 = np.concatenate((arr16, arr21), axis=1)
print('arr16: 元の配列①(2×2)\n', arr16, '\n')
print('arr21: 元の配列④(2×1)\n', arr21, '\n')
print('arr22: 新しい配列 np.concatenate((arr16, arr21), axis=1)\n', arr22)
ただし行数が異なっている配列同士を連結しようとするとエラーになります。
''' 行数が異なっていればエラー '''
# 元の配列⑤(3×2)
arr23 = np.arange(6).reshape(3, 2)
print('arr16: 元の配列①(2×2)\n', arr16, '\n')
print('arr23: 元の配列⑤(3×2)\n', arr23, '\n')
# arr16とarr23は行数が異なるので連結できない
np.concatenate((arr16, arr23), axis=1)
なお、これは2次元配列同士で、np.hstack()を実行しているのと同じことになります。3次元配列までの場合は、そちらを使うことが多いので、以下のページで確認しておきましょう。
1.2.3. axis=Noneの場合は戻り値は1次元配列になる
「axis=None」を指定した場合、元の配列のshapeがどうであれ、1次元配列として連結されます。そのため、この場合は連結する配列同士のshapeを気にする必要はありません。
以下のコードで確認しておきましょう。
# 元の配列①(1×3)
arr24 = np.arange(3).reshape(1, 3)
# 元の配列②(2×2)
arr25 = np.arange(4, 8).reshape(2, 2)
# 元の配列③(3×2)
arr26 = np.arange(9, 15).reshape(3, 2)
# 2つの配列を連結
arr27 = np.concatenate((arr24, arr25), axis=None)
# 3つの配列を連結
arr28 = np.concatenate((arr24, arr25, arr26), axis=None)
print('arr24: 元の配列①\n', arr24, '\n')
print('arr25: 元の配列②\n', arr25, '\n')
print('arr26: 元の配列③\n', arr26, '\n')
print('arr27: np.concatenate((arr24, arr25), axis=None)\n', arr27, '\n')
print('arr28: np.concatenate((arr24, arr25, arr26), axis=None)\n', arr28, '\n')
1.3. 3次元配列同士の連結
次に3次元配列同士の連結を見ていきましょう。
3次元配列では、奥行き×行×列の3つの軸があります。そのため、axis=0で奥行きを、axis=1で行を、axis=2で列を連結します。
それぞれ実際のコードで確認していきましょう。
1.3.1. axis=0(デフォルト値)の場合は奥行きを連結
「axis=」を指定しない場合、デフォルトの「axis=0」の軸で配列を連結します。3次元配列では「axis=0」は奥行きなので、奥行きとして連結していきます。
例えば、shape(N, a, b)の3次元配列を2つ連結すればshape(2N, a, b)に、3つ連結すればshape(3N, a, b)になります。
以下のコードでは、shape(2, 2, 3)の3次元配列を2つ連結しているので、shape(4, 2, 3)の配列になっていますね。
''' axis=0(デフォルト値)では奥行きを連結 '''
import numpy as np
# 元の3次元配列①
arr1 = np.arange(12).reshape(2, 2, 3)
# 元の3次元配列②
arr2 = np.arange(12, 24).reshape(2, 2, 3)
# ①と②を連結
arr3 = np.concatenate((arr1, arr2))
print('arr1: 元の3次元配列①\n', arr1, '\n')
print('arr2: 元の3次元配列②\n', arr2, '\n')
print('arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2))\n', arr3, '\n')
print('新しい配列arr3のshape\n', arr3.shape)
3次元配列を「axis=0」で連結する場合は、行数(axis=1)と列数(axis=2)が揃っていれば、奥行きは異なっても連結することができます。
しかし、行数と列数のいずれか一方でも異なっていればエラーになります。
''' axis=0(奥行き)以外の要素が一つでも揃っていないとエラー '''
# shape(3, 3, 2)の3次元配列④
arr4 = np.arange(12, 30).reshape(3, 3, 2)
print('元の配列① shape(2, 2, 3)\n', arr1, '\n')
print('元の配列④ shape(3, 3, 2)\n', arr4, '\n')
# axis=0(奥行き)以外の要素が揃っていないのでエラーになります。
np.concatenate((arr1, arr4))
なお、np.concatenate()で3次元配列をaxis=0で連結するのは、np.vstack()で3次元配列を重ねることと同じです。
np.vstack() は、主に3次元までの配列を操作するのによく使います。以下で解説しているのであわせて確認すると良いでしょう。
1.3.2. axis=1の場合は行を連結
3次元配列の「axis=1」は行です。そのため「axis=1」を指定すると、行として連結していきます。
例えば、shape(a, N, b)の3次元配列を2つ連結すればshape(a, 2N, b)、3つ連結すればshape(a, 3N, b)の配列になります。
以下のコードでは、shape(2, 2, 3)の3次元配列を2つ連結しているので、shaape(2, 4, 3)の配列になっています。
''' axis=1では行を連結 '''
import numpy as np
# 元の3次元配列①
arr1 = np.arange(12).reshape(2, 2, 3)
# 元の3次元配列②
arr2 = np.arange(12, 24).reshape(2, 2, 3)
# ①と②を連結
arr3 = np.concatenate((arr1, arr2), axis=1)
print('arr1: 元の3次元配列①\n', arr1, '\n')
print('arr2: 元の3次元配列②\n', arr2, '\n')
print('arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2), axis=1)\n', arr3, '\n')
print('新しい配列arr3のshape\n', arr3.shape)
「axis=1」で3次元配列を連結する場合は、奥行き(axis=0)と列数(axis=2)が揃っていれば、行数が異なっても連結可能です。
しかし、奥行きと列数のどちらか一方でも揃っていなければ、次のようにエラーになります。
''' axis=1(行数)以外の要素が一つでも揃っていないとエラー '''
# shape(3, 2, 3)の3次元配列④を生成
arr4 = np.arange(12, 30).reshape(3, 2, 3)
print('元の配列① shape(2, 2, 3)\n', arr1, '\n')
print('元の配列④ shape(3, 2, 3)\n', arr4, '\n')
# axis=1(行数)以外の要素が揃っていないのでエラーになります。
np.concatenate((arr1, arr4), axis=1)
なお、np.concatenate()で3次元配列をaxis=1で連結するのは、np.hstack()で3次元配列を重ねることと同じです。
np.hstack() は主に3次元までの配列を操作するのによく使います。以下で解説しているのであわせて確認すると良いでしょう。
1.3.3. axis=2の場合は列を連結
3次元配列の「axis=2」は列です。そのため「axis=2」を指定すると、列で連結していきます。
例えば、shape(a, b, N)の3次元配列を2つ連結すればshape(a, b, 2N)、3つ連結すればshape(a, b, 3N)の3次元配列になります。
以下のコードでは、shape(2, 2, 3)の3次元配列同士を連結しているので、shape(2, 2, 6)の配列になります。
''' axis=2では列を連結 '''
import numpy as np
# 元の3次元配列①
arr1 = np.arange(12).reshape(2, 2, 3)
# 元の3次元配列②
arr2 = np.arange(12, 24).reshape(2, 2, 3)
# ①と②を連結
arr3 = np.concatenate((arr1, arr2), axis=2)
print('arr1: 元の3次元配列①\n', arr1, '\n')
print('arr2: 元の3次元配列②\n', arr2, '\n')
print('arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2), axis=2)\n', arr3, '\n')
print('新しい配列arr3のshape\n', arr3.shape)
「axis=2」で3次元配列を連結する場合は、奥行き(axis=0)と行数(axis=1)が揃っていれば可能です。
しかし、奥行きと行数のどちらか一方でも揃っていなければ、以下のようにエラーになります。
''' axis=2(列)以外の要素が一つでも揃っていないとエラー '''
# shape(3, 2, 3)の3次元配列④を生成
arr4 = np.arange(12, 18).reshape(1, 2, 3)
print('元の配列① shape(1, 2, 3)\n', arr1, '\n')
print('元の配列④ shape(3, 3, 2)\n', arr4, '\n')
# axis=1(行数)以外の要素が揃っていないのでエラーになります。
np.concatenate((arr1, arr4), axis=1)
なお、np.concatenate()で3次元配列を「axis=2」で連結するのは、np.dstack()で3次元配列を重ねることと同じです。
np.dstack() は、主に3次元までの配列を操作するのによく使います。以下で解説しているのであわせて確認すると良いでしょう。
1.3.4. axis=Noneの場合は戻り値は1次元配列になる
axis=Noneの場合は2次元配列同士を連結する場合と同様に、1次元配列として連結されます。
これは2次元配列の場合と同じなので、サンプルコードは割愛します。
2. まとめ
以上が、numpy.concatenate()の使い方です。NumPyの配列の連結には、以下の関数もよく使うので、併せて確認しておきましょう。
コメント