この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:12:00

タイトル: 多次元配列の構造の確認
SEOタイトル: NumPy 多次元配列の構造確認完全ガイド (shape / ndim / dtype / reshape)

この記事の要点
  • NumPy 配列の構造確認 4 大属性: shape / ndim / size / dtype
  • shape は次元ごとの長さの tuple、ndim は次元数、size は総要素数、dtype は要素の型
  • メモリサイズ確認: itemsize (1 要素のバイト数) × size = nbytes
  • 形状変換: reshape / flatten / ravel / transpose
  • メモリレイアウト: C 順 (行優先) がデフォルト、order="F" で Fortran 順 (列優先)

NumPy 配列の主要属性

NumPy ndarray はベクトル化計算と多次元データの基盤です。Broadcasting や行列演算でハマったとき、まず形状 (shape) を確認するのが鉄則です。

属性戻り値用途
arr.shapetuple各次元の長さ
arr.ndimint次元数
arr.sizeint総要素数
arr.dtypedtype要素の型 (int32, float64...)
arr.itemsizeint1 要素のバイト数
arr.nbytesint配列全体のバイト数
arr.flagsflagsメモリレイアウト (C/F 順) など
arr.stridestuple各軸を 1 進むのに必要なバイト数

具体例

import numpy as np

# 2 次元配列 (3 行 4 列)
arr = np.array([
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
])

arr.shape        # (3, 4)
arr.ndim         # 2
arr.size         # 12
arr.dtype        # dtype('int64')  (Windows では int32 のことも)
arr.itemsize     # 8 (int64 = 8 バイト)
arr.nbytes       # 96 (8 * 12)

# 3 次元配列 (バッチ画像)
imgs = np.zeros((32, 224, 224, 3), dtype=np.float32)
imgs.shape       # (32, 224, 224, 3)
imgs.ndim        # 4
imgs.size        # 32*224*224*3 = 4_816_896
imgs.nbytes      # 19_267_584 (約 19 MB)

np.info() / repr() でまとめて確認

np.info(arr)
# class:  ndarray
# shape:  (3, 4)
# strides:  (32, 8)
# itemsize:  8
# aligned:  True
# contiguous:  True
# fortran:  False
# data pointer: 0x...
# byteorder:  little
# byteswap:  False
# type: int64

print(repr(arr))
# array([[ 1,  2,  3,  4],
#        [ 5,  6,  7,  8],
#        [ 9, 10, 11, 12]])

dtype 一覧

dtypeサイズ範囲 / 説明
int8 / uint81 byte-128~127 / 0~255 (画像で頻出)
int16 / uint162 byte音声 PCM 等
int32 / uint324 byteWindows 規定の int
int64 / uint648 byteLinux 規定の int
float162 byte半精度 (GPU 推論)
float324 byte単精度 (深層学習標準)
float648 byte倍精度 (Python の float 相当)
complex64/1288/16 byte複素数
bool_1 byteTrue/False
object_Python オブジェクト (遅いので避ける)
<U1040 byteUnicode 文字列 (最大 10 文字)
# dtype 指定
arr = np.array([1, 2, 3], dtype=np.float32)
arr.dtype                 # dtype('float32')

# 型変換
arr2 = arr.astype(np.int8)

# よくあるバグ: float が混じると全体が float に
arr = np.array([1, 2, 3, 4.5])
arr.dtype                 # dtype('float64')   ← int じゃない!

形状変換

a = np.arange(12)
a.shape              # (12,)

# reshape (新しい view を返す)
b = a.reshape(3, 4)
b.shape              # (3, 4)

# -1 で自動推論 (1 つだけ可)
c = a.reshape(2, -1)         # (2, 6)
d = a.reshape(-1, 4)         # (3, 4)

# 平坦化
b.flatten()          # コピー (新規配列)
b.ravel()            # view (元と共有)

# 軸の入れ替え
img = np.zeros((224, 224, 3))   # H, W, C
img_chw = img.transpose(2, 0, 1)  # C, H, W (PyTorch 形式)
img.shape, img_chw.shape          # (224, 224, 3), (3, 224, 224)

# 次元追加
v = np.array([1, 2, 3])           # shape (3,)
v[:, None].shape                  # (3, 1)
v[None, :].shape                  # (1, 3)
np.expand_dims(v, axis=0).shape   # (1, 3)

Broadcasting の前提として shape を見る

NumPy の Broadcasting は末尾から各次元を比較し、同じか 1 なら適合します。事故を避けるには毎回 shape を確認します。

A = np.ones((3, 4))      # shape (3, 4)
B = np.ones(4)           # shape (4,)   → 末尾合致、(1, 4) に拡張
C = A + B                # shape (3, 4)

D = np.ones((3, 1))      # shape (3, 1)
E = A + D                # shape (3, 4)   ← 列方向に拡張

F = np.ones((3,))        # shape (3,)
# A + F  → ❌ ValueError: shape (3,) cannot broadcast with (3, 4)
# A.shape の末尾が 4 で、F は 3 なので不一致

メモリレイアウト (C 順 / F 順)

NumPy 配列はデフォルトでC 順 (行優先)。Fortran や MATLAB から移植したコードは F 順を期待することがあります。

arr_c = np.arange(12).reshape(3, 4)         # 規定で C 順
arr_f = np.arange(12).reshape(3, 4, order='F')

arr_c.flags['C_CONTIGUOUS']   # True
arr_c.flags['F_CONTIGUOUS']   # False

arr_c.strides                 # (32, 8)    行→列に進むのに 32 byte
arr_f.strides                 # (8, 24)    列方向に 8 byte

# transpose は基本 view (データは動かない)
arr_t = arr_c.T
arr_t.flags['C_CONTIGUOUS']   # False
arr_t.flags['F_CONTIGUOUS']   # True

list / Pandas との相互変換

# NumPy → Python list
arr.tolist()
# [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

# Pandas DataFrame に
import pandas as pd
df = pd.DataFrame(arr, columns=['a', 'b', 'c', 'd'])
df.shape                  # (3, 4)
df.dtypes                 # int64 each

# DataFrame → NumPy
df.to_numpy()             # → ndarray
df.values                 # 旧 API (非推奨)

デバッグ Tips

# よくあるバグ調査の流れ
def debug_shape(name, arr):
    print(f&quot;{name}: shape={arr.shape} ndim={arr.ndim} &quot;
          f&quot;dtype={arr.dtype} size={arr.size} nbytes={arr.nbytes}&quot;)

debug_shape('X', X)
debug_shape('W', W)
debug_shape('y', y)

# assert で形状を保証
def matmul(A, B):
    assert A.ndim == 2 and B.ndim == 2, f&quot;need 2D, got {A.ndim}D and {B.ndim}D&quot;
    assert A.shape[1] == B.shape[0], f&quot;shape mismatch: {A.shape} @ {B.shape}&quot;
    return A @ B

FAQ

Q: shapelen() の違いは?
A: len(arr) は最初の次元の長さ (= shape[0]) しか返しません。多次元は必ず shape

Q: メモリ使用量を減らしたい
A: 用途に応じて dtype を絞る。画像なら uint8、フラグなら bool。深層学習は float32 / float16 で十分なことが多い。

Q: shape が (N,)(N, 1) で何が違う?
A: 前者は 1 次元ベクトル、後者は 2 次元の列ベクトル。行列演算で動作が変わるため、Broadcasting の挙動を確認しながら使う。