NumPy配列ndarrayに新たな次元を追加するnp.newaxis

NumPy配列ndarrayに新たな次元を追加したい場合、np.newaxisを使う方法があります。

Constants: numpy.newaxis — NumPy v1.16 Manual Indexing — NumPy v1.16 Manual

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

np.newaxisはNone np.newaxisの使い方 np.newaxisでブロードキャストを制御 reshape()で新たな次元を追加する方法

np.newaxisはNone

np.newaxisはNoneのエイリアス。

import numpy as np

print(np.newaxis is None)
# True

分かりやすくするように別名が付けられているだけなので、以下のサンプルコードのnp.newaxisはNoneに置き換えても同じように動作します。

np.newaxisの使い方

[]によるインデックスの中でnp.newaxisを使うとその位置にサイズが1の新たな次元が追加される。

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

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

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

print(a[:, :, np.newaxis].shape)
# (2, 3, 1)


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

print(a[:, np.newaxis, :].shape)
# (2, 1, 3)


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

print(a[np.newaxis, :, :].shape)
# (1, 2, 3)

複数のnp.newaxisを一度に使っても問題ありません。

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

print(a[np.newaxis, :, np.newaxis, :, np.newaxis].shape)
# (1, 2, 1, 3, 1)

np.newaxisでブロードキャストを制御

NumPy配列ndarray同士の二項演算(四則演算など)ではブロードキャスト(broadcasting)という仕組みによりそれぞれの形状shapeが同じになるように自動的に変換される。

a = np.zeros(27, dtype=np.int).reshape(3, 3, 3)
print(a)
# [[[0 0 0]
#   [0 0 0]
#   [0 0 0]]
#
#  [[0 0 0]
#   [0 0 0]
#   [0 0 0]]
#
#  [[0 0 0]
#   [0 0 0]
#   [0 0 0]]]

print(a.shape)
# (3, 3, 3)

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

print(b.shape)
# (3, 3)

print(a + b)
# [[[0 1 2]
#   [3 4 5]
#   [6 7 8]]
#
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]
#
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]]

np.newaxisで先頭に新たな次元を追加した場合はブロードキャストにより自動的に変換された場合と同じ結果になる。

print(b[np.newaxis, :, :].shape)
# (1, 3, 3)

print(a + b[np.newaxis, :, :])
# [[[0 1 2]
#   [3 4 5]
#   [6 7 8]]
#
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]
#
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]]

追加する位置を変えると異なる結果となります。

print(b[:, np.newaxis, :].shape)
# (3, 1, 3)

print(a + b[:, np.newaxis, :])
# [[[0 1 2]
#   [0 1 2]
#   [0 1 2]]
#
#  [[3 4 5]
#   [3 4 5]
#   [3 4 5]]
#
#  [[6 7 8]
#   [6 7 8]
#   [6 7 8]]]


print(b[:, :, np.newaxis].shape)
# (3, 3, 1)

print(a + b[:, :, np.newaxis])
# [[[0 0 0]
#   [1 1 1]
#   [2 2 2]]
#
#  [[3 3 3]
#   [4 4 4]
#   [5 5 5]]
#
#  [[6 6 6]
#   [7 7 7]
#   [8 8 8]]]

例えば、カラー画像の配列(形状: (高さ, 幅, 色))と単色画像(形状: (高さ, 幅))の配列を同じ位置同士で足したり引いたりしたい場合、そのままだとブロードキャストできずにエラーとなるが、単色画像の最後に新たな次元を追加するとうまくいく。このあたりの説明も以下の記事を参照。

reshape()で新たな次元を追加する方法

配列ndarrayの形状shapeを変換する方法としてreshape()メソッドがあります。

reshape()メソッドに新たな次元を追加した形状を指定すれば当然ながらそのように変換される。np.newaxisを使った場合と同じ結果となります。

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

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

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

print(a[:, :, np.newaxis].shape)
# (2, 3, 1)

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

print(a.reshape(2, 3, 1).shape)
# (2, 3, 1)

上の例からも分かるようにnp.newaxisを使うと追加する次元以外の次元のサイズ(元の次元のサイズ)を明示的に指定する必要がない、というメリットがあります。 reshape()でも、最初か最後に次元を追加する場合は、*を使ってタプルを展開して引数に指定することで、サイズを明示的に指定しなくてもよくなる。お好みで。

print(a.reshape(*a.shape, 1))
# [[[0]
#   [1]
#   [2]]
#
#  [[3]
#   [4]
#   [5]]]

print(a.reshape(*a.shape, 1).shape)
# (2, 3, 1)

シェア

関連カテゴリー

Python NumPy

NumPyで空の配列ndarrayを生成するemptyとempty_like NumPyで全要素を同じ値で初期化した配列ndarrayを生成 Pythonのリストと配列とnumpy.ndarrayの違いと使い分け NumPy配列ndarrayの条件を満たす要素数をカウント NumPyのsortとargsort関数で任意の行・列を基準にソート Pythonで正規化・標準化(リスト、NumPy配列、pandas.DataFrame) pandasからNumPyの関数などを使う方法(pd.np) Python, OpenCV, Pillow(PIL)で画像サイズ(幅、高さ)を取得 pandas参考書『Pythonによるデータ分析入門』の注意点 pandas参考書『Python for Data Analysis, 2nd Edition』 NumPy配列ndarrayの次元数、形状、サイズ(全要素数)を取得 Python, NumPyで画像処理(読み込み、演算、保存) NumPyのバージョンを確認(np.version) NumPyのarange, linspaceの使い方(連番や等差数列を生成) NumPy, randomで様々な種類の乱数の配列を生成

Last Updated: 6/26/2019, 10:34:03 PM