np.newaxisとnp.expand_dimsの使い方|NumPy配列に次元を追加する方法と違い・使い分け

NumPy配列に長さ1の次元(軸)を足すには、インデックスに書く arr[np.newaxis, :](np.newaxis は None の別名)か、関数の np.expand_dims(arr, axis=0) を使います。結果は同じで、位置を角括弧の中で示すか、axis の番号で指定するかの違いです。

この記事では、形(shape)が (4,) の配列が、書き方によってどの形になるかを早見表で示し、二つの使い分け、機械学習の「バッチ次元」やブロードキャストでの使いどころ、よくあるエラーまでを実行結果つきでまとめます。コードはNumPy 2.5.4(Python 3.12)で実行しました(2026年10月15日確認)。

早見表:書き方と結果の形

元の配列は arr = np.array([1, 2, 3, 4])(shapeは (4,))です。

やりたいこと np.newaxis(None) np.expand_dims 結果のshape
先頭に軸を足す(行ベクトル) arr[np.newaxis, :] / arr[None] np.expand_dims(arr, axis=0) (1, 4)
末尾に軸を足す(列ベクトル) arr[:, np.newaxis] / arr[..., None] np.expand_dims(arr, axis=1) または axis=-1 (4, 1)
前後の両方に足す arr[np.newaxis, :, np.newaxis] np.expand_dims(arr, axis=(0, 2)) (1, 4, 1)

どちらも新しい軸の長さは1で、要素の数や並びは変わりません。変わるのは「何次元の配列として扱うか」だけです。

np.newaxisの使い方

np.newaxis は、公式ドキュメントで「インデックス指定に便利な None の別名」と説明されている定数です(NumPy: Constants)。角括弧の中で、軸を足したい位置に置きます。: は「元の軸をそのまま残す」という意味です。

import numpy as np

arr = np.array([1, 2, 3, 4])
print(arr.shape)

row = arr[np.newaxis, :]   # 先頭に軸を追加
col = arr[:, np.newaxis]   # 末尾に軸を追加
print(row, row.shape)
print(col, col.shape)
print(np.newaxis is None)
print(arr[None].shape, arr[..., None].shape)
(4,)
[[1 2 3 4]] (1, 4)
[[1]
 [2]
 [3]
 [4]] (4, 1)
True
(1, 4) (4, 1)

np.newaxis is None が True になるとおり、arr[None] と書いても同じ結果です。読み手に「軸を足している」と伝わりやすいので、記事やチーム開発では np.newaxis と書くことが多いです。

...(Ellipsis)は「残りの軸すべて」を表します。arr[..., np.newaxis] は元の次元数に関係なく末尾に軸を足すので、2次元でも3次元でも同じ書き方で済みます。

2次元配列に使うと

2次元の配列では、np.newaxis を置く位置で結果が変わります。

import numpy as np

m = np.zeros((2, 3))
print(m[np.newaxis].shape)
print(m[:, np.newaxis].shape)
print(m[:, :, np.newaxis].shape)
print(m[np.newaxis, :, np.newaxis].shape)
print(m[..., np.newaxis].shape)
(1, 2, 3)
(2, 1, 3)
(2, 3, 1)
(1, 2, 1, 3)
(2, 3, 1)

一つの角括弧に np.newaxis を複数書けば、一度に複数の軸を足せます。

np.expand_dimsの使い方

np.expand_dims(a, axis) は、「足したあとの配列で、新しい軸が何番目に来るか」を axis で指定する関数です。axis には整数のほか整数のタプルも渡せて、複数の軸を一度に足せます(numpy.expand_dims)。

import numpy as np

arr = np.array([1, 2, 3, 4])
print(np.expand_dims(arr, axis=0).shape)
print(np.expand_dims(arr, axis=1).shape)
print(np.expand_dims(arr, axis=-1).shape)
print(np.expand_dims(arr, axis=(0, 2)).shape)

m = np.zeros((2, 3))
for ax in [0, 1, 2, -1]:
    print(ax, np.expand_dims(m, axis=ax).shape)
(1, 4)
(4, 1)
(4, 1)
(1, 4, 1)
0 (1, 2, 3)
1 (2, 1, 3)
2 (2, 3, 1)
-1 (2, 3, 1)

axis=-1 は「末尾」です。元の次元数が分からない関数の中でも末尾に足せるので、arr[..., np.newaxis] と同じ使い方ができます。

np.newaxisとnp.expand_dimsの違いと使い分け

np.newaxis np.expand_dims
正体 定数(None の別名) 関数
位置の指定 角括弧の中に置く場所 axis の番号
複数の軸 角括弧に複数書く axis=(0, 2) のようにタプルで渡す
スライスとの組み合わせ arr[1:3, np.newaxis] のように一度に書ける 先に切り出してから呼ぶ
軸の位置を変数で決めたいとき 書きにくい axis=ax と渡すだけ
結果 どちらも元の配列のビュー(データはコピーされない)

目安としては、数式に近い短い式(列ベクトルにして掛け算する、など)は np.newaxis、関数の引数で軸の位置を受け取る場合や「何番目の軸か」を明示したい場合は np.expand_dims が読みやすくなります。

なお、古い解説には「expand_dimsは一度に一つの軸しか足せない」と書かれたものがありますが、現在のドキュメントでは axis に整数のタプルを渡せます(上の axis=(0, 2) の例)。

使いどころ1:1件のデータにバッチ次元を足す

KerasやPyTorchのモデルは、データを「何件かまとめたもの(バッチ)」として受け取ります。28×28の画像1枚を予測に渡すときは、先頭にバッチの軸、Keras(チャンネルが最後の形式)なら末尾にチャンネルの軸を足して (1, 28, 28, 1) にします。

import numpy as np

img = np.random.default_rng(0).random((28, 28))  # 1枚のグレースケール画像
x = img[np.newaxis, ..., np.newaxis]             # (バッチ, 高さ, 幅, チャンネル)
print(x.shape)
print(np.expand_dims(img, axis=(0, -1)).shape)
(1, 28, 28, 1)
(1, 28, 28, 1)

Keras 3.15.1で軸を足さずに (28, 28) のまま予測に渡すと「Expected shape (None, 28, 28, 1), but input has incompatible shape (28, 28)」というエラーになりました。このようなエラーが出たら、まずこのバッチ次元が足りているかを確認します。Kerasでの予測までの流れは「Kerasとは?」で実行例つきで扱っています。

使いどころ2:ブロードキャストで形を合わせる

形の違う配列同士の計算(ブロードキャスト)は、後ろの軸から順に長さが「同じ」か「どちらかが1」のときだけ通ります。長さ1の軸を足すと、計算の向きを指定できます。

import numpy as np

a = np.array([1, 2, 3])
b = np.array([10, 20])
try:
    a * b
except ValueError as e:
    print("ValueError:", e)

print(a[:, np.newaxis] * b)          # (3,1) と (2,) → (3,2)

pts = np.array([[0, 0], [3, 4], [6, 8]])
diff = pts[:, np.newaxis, :] - pts[np.newaxis, :, :]
print(diff.shape)
print(np.sqrt((diff ** 2).sum(axis=-1)))
ValueError: operands could not be broadcast together with shapes (3,) (2,)
[[10 20]
 [20 40]
 [30 60]]
(3, 3, 2)
[[ 0.  5. 10.]
 [ 5.  0.  5.]
 [10.  5.  0.]]

1つ目は長さ3と長さ2の掛け算でエラーになりますが、a を列ベクトル (3, 1) にすると「全組み合わせの積」の表(外積)になります。2つ目は3点の座標から、すべての点の組の距離を一度に求めた例です。ループを書かずに済むのが、軸を足す一番の利点です。

行ごとの平均を引く(keepdimsとの比較)

import numpy as np

scores = np.array([[60, 70, 80],
                   [90, 50, 70]])
mean = scores.mean(axis=1)            # 行ごとの平均 shape (2,)
print(mean.shape)
try:
    scores - mean
except ValueError as e:
    print("ValueError:", e)
print(scores - mean[:, np.newaxis])
print(scores - scores.mean(axis=1, keepdims=True))
(2,)
ValueError: operands could not be broadcast together with shapes (2,3) (2,)
[[-10.   0.  10.]
 [ 20. -20.   0.]]
[[-10.   0.  10.]
 [ 20. -20.   0.]]

集計で軸が消えた配列は、[:, np.newaxis] で戻すと引き算できます。集計の段階で keepdims=True を付けて軸を残しておく方法でも同じ結果です。ブロードキャストのルールとエラーの直し方は「NumPyのブロードキャストとは?」で詳しく扱っています。

結果はビュー:元の配列と同じデータを指す

np.expand_dims も np.newaxis も、データをコピーせず元の配列の「見え方」だけを変えたビューを返します(expand_dimsの戻り値はドキュメントにも「次元数を増やした a のビュー」とあります)。そのため、結果に書き込むと元の配列も変わります。

import numpy as np

arr = np.array([1, 2, 3, 4])
v = np.expand_dims(arr, axis=0)
v[0, 0] = 100
print(arr)
print(np.shares_memory(arr, v), np.shares_memory(arr, arr[:, None]))
c = np.expand_dims(arr, axis=0).copy()
c[0, 0] = -1
print(arr)
[100   2   3   4]
True True
[100   2   3   4]

元の配列を守りたいときは .copy() を付けます。コピーしないぶん、大きな配列でも軸を足す処理そのものはほとんど時間がかかりません。

reshape・atleast_2d・squeezeとの関係

軸を足す方法はほかにもあります。逆に長さ1の軸を取り除くのが np.squeeze です(numpy.squeeze)。

import numpy as np

arr = np.array([1, 2, 3, 4])
print(arr.reshape(1, -1).shape, arr.reshape(-1, 1).shape)
print(np.atleast_2d(arr).shape)
x = arr[np.newaxis, :, np.newaxis]
print(x.shape, np.squeeze(x).shape, np.squeeze(x, axis=0).shape)
try:
    np.expand_dims(arr, axis=2)
except Exception as e:
    print(type(e).__name__, ":", e)
try:
    np.squeeze(np.zeros((2, 3)), axis=0)
except Exception as e:
    print(type(e).__name__, ":", e)
(1, 4) (4, 1)
(1, 4)
(1, 4, 1) (4,) (4, 1)
AxisError : axis 2 is out of bounds for array of dimension 2
ValueError : cannot select an axis to squeeze out which has size not equal to one
方法 向いている場面
reshape(1, -1) / reshape(-1, 1) 2次元にすると決まっているとき。軸を足すだけでなく並べ替え全般に使える
np.atleast_2d 「1次元なら2次元にし、すでに2次元以上ならそのまま」にしたいとき
np.newaxis / np.expand_dims 任意の位置に長さ1の軸を足したいとき
np.squeeze 長さ1の軸を取り除く(逆の操作)

np.expand_dims(arr, axis=2) のエラーは、1次元の配列に軸を1つ足すと2次元になり、使える axis は0、1(または-1、-2)だけだからです。範囲外の axis は AxisError になります。形の確認には shape と ndim を使います(「NumPy配列の次元数・形状・要素数を取得する方法」)。1次元配列を行と列に並べ直す方法は「Pythonで一次元配列を二次元配列に変換する方法」にまとめています。

よくある質問

Q. np.newaxisとNoneは同じですか?

同じです。np.newaxisはNoneの別名なので、arr[np.newaxis, :] と arr[None, :] は同じ結果になります。軸を足していることが伝わりやすいので、np.newaxisと書く人が多いです。

Q. np.expand_dimsで一度に複数の軸を足せますか?

足せます。np.expand_dims(arr, axis=(0, 2)) のように整数のタプルを渡すと、shapeが(4,)の配列は(1, 4, 1)になります。

Q. 行ベクトルと列ベクトルはどう作り分けますか?

行ベクトル(1, n)は arr[np.newaxis, :] か np.expand_dims(arr, axis=0)、列ベクトル(n, 1)は arr[:, np.newaxis] か np.expand_dims(arr, axis=1) です。reshape(1, -1) と reshape(-1, 1) でも同じ形になります。

Q. 追加した次元を元に戻すには?

np.squeeze で長さ1の軸を取り除きます。axisを指定すればその軸だけを取り除けますが、長さが1でない軸を指定するとValueErrorになります。

Q. 軸を足すと配列はコピーされますか?

コピーされません。結果は元の配列のビューなので、結果に書き込むと元の配列も変わります。分けたいときは .copy() を付けます。

まとめ

  • arr[np.newaxis, :] と np.expand_dims(arr, axis=0) は同じ結果。先頭に足すと行ベクトル (1, n)、末尾に足すと列ベクトル (n, 1)
  • np.newaxis は None の別名。... と組み合わせると次元数に関係なく末尾に足せる
  • np.expand_dims は axis にタプルを渡して複数の軸を一度に足せる
  • 主な用途はモデルに渡すときのバッチ次元と、ブロードキャストの向きの指定
  • 結果はビュー。戻すときは np.squeeze

NumPy|行列・線形代数の関連記事

行列演算やブロードキャストなど、線形代数まわりの記事です。

NumPy全体の使い方は「NumPyの使い方」、「NumPy関数一覧」でまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら