numpy.concatenate – 配列同士を連結

numpy.concatenateは、配列同士を連結して新しい配列を生成する関数です。行や列のどちらを軸として連結するのかを、axis=によって指定する必要があります。

ここで、実際のコードを見ながら、使い方を確認していきましょう。

目次

1. numpy.concatenateの使い方

まずは基本的な書き方を確認しましょう。

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

一緒に確認したい関数:

  • ma.concatenate
  • stack: 配列を重ねて次元数が1つ上の配列を生成
  • hstack: 配列を水平に連結
  • vstack: 配列を垂直に連結
  • dstack: 配列を奥行き方向に連結
  • array_split
  • split
  • hsplit
  • vsplit
  • dsplit

それでは、実際のコードで一通り確認していきましょう。

1.1. 1次元配列同士の連結

まずは、1次元配列同士の連結を見ていきましょう。

注意点として、連結する配列はタプルかリストで渡す点を確認しましょう。また配列は3つ以上でも、好きなだけ連結することができます。

In [1]:
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')
arr1: 元の配列①
 [0 1 2 3] 

arr2: 元の配列②
 [4 5] 

arr3: 元の配列③
 [ 7  8  9 10] 

arr4: 新しい配列
 [0 1 2 3 4 5] 

arr5: 3つの配列を連結した新しい配列
 [ 0  1  2  3  4  5  7  8  9 10] 

元の配列に連結するのではなく、要素を連結した新しい配列を生成する点をおさえておきましょう。

tips: オプション引数「out=」で既存の配列を変更

もし、np.concatenate()で連結した配列で、既存の配列を変更したい場合はオプション引数「out=」を使います。

以下のコードでは、初期化した配列arr6を生成し、それをarr1とarr2の連結結果に変更するように指定しています。

In [2]:
#  新しい配列を生成
arr6 = np.zeros(6, int)
print('関数実行前のarr6\n', arr6, '\n')

#  arr1とarr2を連結した配列をarr6に代入
np.concatenate((arr1, arr2), out=arr6)
print('関数実行後のarr6\n', arr6)
関数実行前のarr6
 [0 0 0 0 0 0] 

関数実行後のarr6
 [0 1 2 3 4 5]

ただし、連結した配列のshapeとout=で指定した配列のshapeが異なる場合、または要素の型(dtype)が異なる場合はエラーになります。shapeやdtypeは『NumPyのarray(配列)の基本的操作まとめ』で解説しています。

In [3]:
'''  連結した配列とout=で指定した配列のshapeや型(dtype)が異なるとエラー  '''
#  1×3の配列を生成
arr7 = np.arange(3)
#  arr7とarr1+arr2はshapeが異なるためエラーになる。
np.concatenate((arr1, arr2), out=arr7)
ValueError: Output array is the wrong shape

なお、「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次元配列になります。

In [4]:
#  元の配列①
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)
arr8: 元の配列①
 [[0 1 2]
 [3 4 5]] 

arr9: 元の配列②
 [[ 6  7  8]
 [ 9 10 11]] 

arr10: 元の配列③
 [[12 13 14]
 [15 16 17]] 

arr11: 2つの配列を連結 np.concatenate((arr6, arr7))
 [[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]] 

arr12: 3つの配列を連結 np.concatenate((arr6, arr7, arr8))
 [[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]
 [15 16 17]]

デフォルト(axis=0)の場合、連結する配列の一行ごとの要素数が揃っていれば連結可能です。

以下のコードでは、shape(2, 3)とshape(1, 3)の配列の連結です。行数は異なりますが、列数は揃っているので連結が実行され、shape(3, 3)の2次元配列になっています。

In [5]:
''' 行数が異なっても一行ごとの要素数が同じなら連結可能  '''
#  元の配列④(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)
arr8: 元の配列①(2×3)
 [[0 1 2]
 [3 4 5]] 

arr13: 元の配列④(1×3)
 [[6 7 8]] 

arr14: 新しい配列 np.concatenate((arr8, arr13))
 [[0 1 2]
 [3 4 5]
 [6 7 8]]

ただし、列数が揃っていない配列を連結しようとするとエラーになります。

In [6]:
'''  一行ごとの要素数が異なっていればエラー  '''
#  元の配列⑤(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))
arr8: 元の配列①(2×3)
 [[0 1 2]
 [3 4 5]] 

arr15: 元の配列④(1×4)
 [[ 9 10 11 12]] 

ValueError: all the input array dimensions except for the concatenation axis must match exactly

なお、これは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)の配列になっています。

In [7]:
#  元の配列①
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)
arr16: 元の配列①
 [[0 1]
 [2 3]] 

arr17: 元の配列②
 [[4 5]
 [6 7]] 

arr18: 元の配列③
 [[ 8  9]
 [10 11]] 

arr19: 2つの配列を連結 np.concatenate((arr16, arr17), axis=1)
 [[0 1 4 5]
 [2 3 6 7]] 

arr20: 3つの配列を連結 np.concatenate((arr16, arr17, arr18), axis=1)
 [[ 0  1  4  5  8  9]
 [ 2  3  6  7 10 11]]

この場合、連結する配列同士の行数が揃っていれば連結可能です。

In [8]:
'''  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)
arr16: 元の配列①(2×2)
 [[0 1]
 [2 3]] 

arr21: 元の配列④(2×1)
 [[13]
 [14]] 

arr22: 新しい配列 np.concatenate((arr16, arr21), axis=1)
 [[ 0  1 13]
 [ 2  3 14]]

ただし行数が異なっている配列同士を連結しようとするとエラーになります。

In [9]:
'''  行数が異なっていればエラー  '''
#  元の配列⑤(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)
arr16: 元の配列①(2×2)
 [[0 1]
 [2 3]] 

arr23: 元の配列⑤(3×2)
 [[0 1]
 [2 3]
 [4 5]] 

ValueError: all the input array dimensions except for the concatenation axis must match exactly

なお、これは2次元配列同士で、np.hstack()を実行しているのと同じことになります。3次元配列までの場合は、そちらを使うことが多いので、以下のページで確認しておきましょう。

1.2.3. axis=Noneの場合は戻り値は1次元配列になる

「axis=None」を指定した場合、元の配列のshapeがどうであれ、1次元配列として連結されます。そのため、この場合は連結する配列同士のshapeを気にする必要はありません。

以下のコードで確認しておきましょう。

In [10]:
#  元の配列①(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')
arr24: 元の配列①
 [[0 1 2]] 

arr25: 元の配列②
 [[4 5]
 [6 7]] 

arr26: 元の配列③
 [[ 9 10]
 [11 12]
 [13 14]] 

arr27: np.concatenate((arr24, arr25), axis=None)
 [0 1 2 4 5 6 7] 

arr28: np.concatenate((arr24, arr25, arr26), axis=None)
 [ 0  1  2  4  5  6  7  9 10 11 12 13 14] 

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)の配列になっていますね。

In [1]:
'''  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)
arr1: 元の3次元配列①
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

arr2: 元の3次元配列②
 [[[12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]]] 

arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2))
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]

 [[12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]]] 

新しい配列arr3のshape
 (4, 2, 3)

3次元配列を「axis=0」で連結する場合は、行数(axis=1)と列数(axis=2)が揃っていれば、奥行きは異なっても連結することができます。

しかし、行数と列数のいずれか一方でも異なっていればエラーになります。

In [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))
元の配列① shape(2, 2, 3)
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

元の配列④ shape(3, 3, 2)
 [[[12 13]
  [14 15]
  [16 17]]

 [[18 19]
  [20 21]
  [22 23]]

 [[24 25]
  [26 27]
  [28 29]]] 

ValueError: all the input array dimensions except for the concatenation axis must match exactly

なお、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)の配列になっています。

In [1]:
'''  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)
arr1: 元の3次元配列①
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

arr2: 元の3次元配列②
 [[[12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]]] 

arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2), axis=1)
 [[[ 0  1  2]
  [ 3  4  5]
  [12 13 14]
  [15 16 17]]

 [[ 6  7  8]
  [ 9 10 11]
  [18 19 20]
  [21 22 23]]] 

新しい配列arr3のshape
 (2, 4, 3)

「axis=1」で3次元配列を連結する場合は、奥行き(axis=0)と列数(axis=2)が揃っていれば、行数が異なっても連結可能です。

しかし、奥行きと列数のどちらか一方でも揃っていなければ、次のようにエラーになります。

In [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)
元の配列① shape(2, 2, 3)
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

元の配列④ shape(3, 3, 2)
 [[[12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]]

 [[24 25 26]
  [27 28 29]]] 

ValueError: all the input array dimensions except for the concatenation axis must match exactly

なお、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)の配列になります。

In [1]:
'''  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)
arr1: 元の3次元配列①
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

arr2: 元の3次元配列②
 [[[12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]]] 

arr3: 2つの3次元配列を連結 np.concatenate((arr1, arr2), axis=2)
 [[[ 0  1  2 12 13 14]
  [ 3  4  5 15 16 17]]

 [[ 6  7  8 18 19 20]
  [ 9 10 11 21 22 23]]] 

新しい配列arr3のshape
 (2, 2, 6)

「axis=2」で3次元配列を連結する場合は、奥行き(axis=0)と行数(axis=1)が揃っていれば可能です。

しかし、奥行きと行数のどちらか一方でも揃っていなければ、以下のようにエラーになります。

In [2]:
'''  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)
元の配列① shape(2, 2, 3)
 [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]] 

元の配列④ shape(3, 3, 2)
 [[[12 13 14]
  [15 16 17]]] 

ValueError: all the input array dimensions except for the concatenation axis must match exactly

なお、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の配列の連結には、以下の関数もよく使うので、併せて確認しておきましょう。

  • stack: 配列を重ねて次元数が1つ上の配列を生成
  • hstack: 配列を水平に連結
  • vstack: 配列を垂直に連結
  • dstack: 配列を奥行き方向に連結



よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次
閉じる