note.nkmk.me

NumPy配列ndarrayの末尾に要素・行・列を追加するappend

Date: 2019-06-16 / tags: Python, NumPy

NumPy配列ndarrayの末尾または先頭に新たな要素や配列(行・列など)を追加するにはnp.append()関数を使う。ndarrayのメソッドにはない。

ここでは以下の内容について説明する。

  • np.append()の基本的な使い方
    • 末尾に要素・配列を追加
    • 先頭に要素・配列を追加
  • 二次元配列のnp.append()
    • 次元(軸)を指定して行・列を追加: 引数axis
    • 注意点(np.vstack(), np.hstack()などとの違い)
  • 三次元以上の多次元配列のnp.append()

本記事内でも適宜紹介するが、複数の配列ndarrayを結合(連結)する方法については以下の記事を参照。

また、先頭や末尾ではなく任意の位置に挿入したい場合はnp.insert()を使う。

スポンサーリンク

np.append()の基本的な使い方

末尾に要素・配列を追加

まず一次元配列を例にしてnp.append()の基本的な使い方を説明する。

第一引数に元の配列ndarray、第二引数に追加する要素を指定する。元の配列はそのままで、新たな配列が返される。

import numpy as np

a = np.arange(3)
print(a)
# [0 1 2]

a_append = np.append(a, 3)
print(a_append)
# [0 1 2 3]

print(a)
# [0 1 2]

第一引数、第二引数にはリストやndarrayなどのいわゆるarray-likeオブジェクトを指定可能。返り値は常にndarray

print(np.append(a, [3, 4, 5]))
# [0 1 2 3 4 5]

print(np.append(a, np.arange(3, 6)))
# [0 1 2 3 4 5]

先頭に要素・配列を追加

末尾ではなく先頭に追加したい場合は、第一引数と第二引数のオブジェクトを入れ替えればよい。

追加したい要素や配列を第一引数に、元の配列を第二引数に指定する。

print(np.append(-1, a))
# [-1  0  1  2]

print(np.append([-3, -2, -1], a))
# [-3 -2 -1  0  1  2]

print(np.append(np.arange(-3, 0), a))
# [-3 -2 -1  0  1  2]

二次元配列のnp.append()

次元(軸)を指定して行・列を追加: 引数axis

二次元配列の場合、デフォルトでは、第一引数の配列ndarrayが一次元に平坦化されてから第二引数の値が末尾に追加された配列が返される。

a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
#  [3 4 5]]

print(np.append(a_2d, 10))
# [ 0  1  2  3  4  5 10]

第二引数が配列の場合も同様。第一引数、第二引数の配列がいずれも一次元に平坦化されて連結される。

a_2d_ex = np.arange(6).reshape(2, 3) * 10
print(a_2d_ex)
# [[ 0 10 20]
#  [30 40 50]]

print(np.append(a_2d, a_2d_ex))
# [ 0  1  2  3  4  5  0 10 20 30 40 50]

次元を保ったまま配列を追加するには引数axisを指定する。axis=0で新たな行として追加(縦に連結)、axis=1で新たな列として追加(横に連結)される。存在しない次元(軸)を指定するとエラー。

print(np.append(a_2d, a_2d_ex, axis=0))
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 0 10 20]
#  [30 40 50]]

print(np.append(a_2d, a_2d_ex, axis=1))
# [[ 0  1  2  0 10 20]
#  [ 3  4  5 30 40 50]]

# print(np.append(a_2d, a_2d_ex, axis=2))
# AxisError: axis 2 is out of bounds for array of dimension 2

axis=0で新たな行として追加する場合は列数が、axis=1で新たな列として追加する場合は行数が、元の配列と一致していなる必要がある。足りない部分が欠損値NaNで埋められたりはしない。

a_2d_ex2 = np.arange(2).reshape(1, 2) * 10
print(a_2d_ex2)
# [[ 0 10]]

# print(np.append(a_2d, a_2d_ex2, axis=0))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

# print(np.append(a_2d, a_2d_ex2, axis=1))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

一次元の例と同様に、第一引数と第二引数を入れ替えると逆の順番になる。

print(np.append(a_2d_ex, a_2d, axis=0))
# [[ 0 10 20]
#  [30 40 50]
#  [ 0  1  2]
#  [ 3  4  5]]

print(np.append(a_2d_ex, a_2d, axis=1))
# [[ 0 10 20  0  1  2]
#  [30 40 50  3  4  5]]

配列ndarrayではなく二次元のリスト(リストのリスト)でもOK。

print(np.append(a_2d, [[0, 10, 20], [30, 40, 50]], axis=0))
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 0 10 20]
#  [30 40 50]]

注意点(np.vstack(), np.hstack()などとの違い)

配列(行や列)を追加する場合、第一引数と第二引数の次元数が一致していないとエラーとなる。

例えば1行だけ追加したい場合も、一次元配列だとエラーで、二次元配列でないとダメ。形状shapeを変換するにはreshape()を使う。

a_row_1d = np.arange(3) * 10
print(a_row_1d)
# [ 0 10 20]

# print(np.append(a_2d, a_row_1d, axis=0))
# ValueError: all the input arrays must have same number of dimensions

a_row_2d = np.arange(3).reshape(1, 3) * 100
print(a_row_2d)
# [[  0 100 200]]

print(np.append(a_2d, a_row_2d, axis=0))
# [[  0   1   2]
#  [  3   4   5]
#  [  0 100 200]]

print(np.append(a_2d, a_row_1d.reshape(1, 3), axis=0))
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 0 10 20]]

行の場合も同様。

a_col_1d = np.arange(2) * 10
print(a_col_1d)
# [ 0 10]

# print(np.append(a_2d, a_col_1d, axis=1))
# ValueError: all the input arrays must have same number of dimensions

a_col_2d = np.arange(2).reshape(2, 1) * 100
print(a_col_2d)
# [[  0]
#  [100]]

print(np.append(a_2d, a_col_2d, axis=1))
# [[  0   1   2   0]
#  [  3   4   5 100]]

print(np.append(a_2d, a_col_1d.reshape(2, 1), axis=1))
# [[ 0  1  2  0]
#  [ 3  4  5 10]]

配列を縦に連結するnp.vstack()では一次元配列をそのまま連結できる。引数に連結したい配列をリストで指定する。複数の配列を一度に連結することも可能。

print(np.vstack([a_2d, a_row_1d]))
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 0 10 20]]

print(np.vstack([a_row_2d, a_2d, a_row_1d, [[0, -1, -2], [-3, -4, -5]]]))
# [[  0 100 200]
#  [  0   1   2]
#  [  3   4   5]
#  [  0  10  20]
#  [  0  -1  -2]
#  [ -3  -4  -5]]

配列を横に連結するnp.hstack()np.append()と同様に次元を合わせる必要があるが、複数の配列を一度に連結することが可能。

# print(np.hstack([a_2d, a_col_1d]))
# ValueError: all the input arrays must have same number of dimensions

print(np.hstack([a_col_2d, a_2d, a_col_1d.reshape(2, 1), [[0, -1], [-2, -3]]]))
# [[  0   0   1   2   0   0  -1]
#  [100   3   4   5  10  -2  -3]]

好みの問題もあるが、二次元配列に二次元配列を追加する場合はnp.vstack()np.hstack()のほうが直感的。

そのほか、二次元配列を深さ方向に連結して三次元配列を生成するnp.dstack()という関数もある。詳細は以下の記事を参照。

三次元以上の多次元配列のnp.append()

三次元以上の多次元配列の場合も考え方は同じ。

デフォルト(axis=None)では配列が一次元に平坦化されてから要素や配列が末尾に追加される。

a_3d = np.arange(12).reshape(2, 3, 2)
print(a_3d)
# [[[ 0  1]
#   [ 2  3]
#   [ 4  5]]
# 
#  [[ 6  7]
#   [ 8  9]
#   [10 11]]]

print(np.append(a_3d, 100))
# [  0   1   2   3   4   5   6   7   8   9  10  11 100]

引数axisを指定するとそれぞれの軸に対して連結される。

三次元以上の多次元配列の場合、出力を見るだけだとどのように連結されたかイメージしにくいので、慣れないうちは形状shapeを確認してみるとよい。

a_3d_ex = np.arange(12).reshape(2, 3, 2) * 10
print(a_3d_ex)
# [[[  0  10]
#   [ 20  30]
#   [ 40  50]]
# 
#  [[ 60  70]
#   [ 80  90]
#   [100 110]]]

print(a_3d_ex.shape)
# (2, 3, 2)

print(np.append(a_3d, a_3d_ex, axis=0))
# [[[  0   1]
#   [  2   3]
#   [  4   5]]
# 
#  [[  6   7]
#   [  8   9]
#   [ 10  11]]
# 
#  [[  0  10]
#   [ 20  30]
#   [ 40  50]]
# 
#  [[ 60  70]
#   [ 80  90]
#   [100 110]]]

print(np.append(a_3d, a_3d_ex, axis=0).shape)
# (4, 3, 2)

print(np.append(a_3d, a_3d_ex, axis=1))
# [[[  0   1]
#   [  2   3]
#   [  4   5]
#   [  0  10]
#   [ 20  30]
#   [ 40  50]]
# 
#  [[  6   7]
#   [  8   9]
#   [ 10  11]
#   [ 60  70]
#   [ 80  90]
#   [100 110]]]

print(np.append(a_3d, a_3d_ex, axis=1).shape)
# (2, 6, 2)

print(np.append(a_3d, a_3d_ex, axis=2))
# [[[  0   1   0  10]
#   [  2   3  20  30]
#   [  4   5  40  50]]
# 
#  [[  6   7  60  70]
#   [  8   9  80  90]
#   [ 10  11 100 110]]]

print(np.append(a_3d, a_3d_ex, axis=2).shape)
# (2, 3, 4)

複数の配列を順に連結したい場合はnp.concatenate()が便利。

print(np.concatenate([a_3d_ex, a_3d, a_3d_ex], axis=2))
# [[[  0  10   0   1   0  10]
#   [ 20  30   2   3  20  30]
#   [ 40  50   4   5  40  50]]
# 
#  [[ 60  70   6   7  60  70]
#   [ 80  90   8   9  80  90]
#   [100 110  10  11 100 110]]]

詳細は以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事