NumPy配列ndarrayの末尾に要素・行・列を追加するappend
NumPy配列ndarray
の末尾または先頭に新たな要素や配列(行・列など)を追加するにはnp.append()
関数を使う。ndarray
にはappend()
メソッドはない。
本記事内でも適宜紹介するが、複数の配列ndarray
を結合(連結)する方法については以下の記事を参照。
また、先頭や末尾ではなく任意の位置に挿入したい場合はnp.insert()
を使う。
本記事のサンプルコードのNumPyのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。
import numpy as np
print(np.__version__)
# 1.26.1
np.append()の基本的な使い方
末尾に要素・配列を追加
まず一次元配列を例にしてnp.append()
の基本的な使い方を説明する。
第一引数に元の配列ndarray
、第二引数に追加する要素を指定する。元の配列はそのままで、新たな配列が返される。
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]
先頭に要素・配列を追加
末尾ではなく先頭に追加するには、第一引数と第二引数のオブジェクトを入れ替えればよい。
追加したい要素や配列を第一引数に、元の配列を第二引数に指定する。
a = np.arange(3)
print(a)
# [0 1 2]
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, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 2
# print(np.append(a_2d, a_2d_ex2, axis=1))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 1 has size 1
一次元の例と同様に、第一引数と第二引数を入れ替えると逆の順番になる。
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
ではなく二次元のリスト(リストのリスト)も指定可能。
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()などとの違い
np.append()
で配列(行や列)を追加する場合、第一引数と第二引数の次元数が一致していないとエラーとなる。
例えば、二次元配列に一行だけ追加したい場合も、二次元配列と一次元配列だとエラーで、どちらも二次元配列でなければならない。形状shape
を変換するにはreshape()
を使う。
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
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, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
print(a_row_1d.reshape(1, 3))
# [[ 0 10 20]]
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, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
print(a_col_1d.reshape(2, 1))
# [[ 0]
# [10]]
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_2d, a_row_1d, [[0, -1, -2], [-3, -4, -5]]]))
# [[ 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, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
print(np.hstack([a_2d, a_col_1d.reshape(2, 1), [[0, -1], [-2, -3]]]))
# [[ 0 1 2 0 0 -1]
# [ 3 4 5 10 -2 -3]]
好みの問題もあるが、二次元配列に二次元配列を追加・連結する場合はnp.vstack()
やnp.hstack()
のほうが直感的。
そのほか、二次元配列を深さ方向に連結して三次元配列を生成するnp.dstack()
という関数もある。詳細は以下の記事を参照。
三次元以上の多次元配列のnp.append()
三次元以上の多次元配列に対する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]]]
詳細は以下の記事を参照。