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

タイトル: 多次元配列を1次元配列に変換
SEOタイトル: NumPy で多次元配列を 1 次元に変換する方法完全ガイド

この記事の要点
  • arr.flatten() は常にコピーを返す(安全)
  • arr.ravel() は可能な限り view を返す(高速・省メモリ)
  • arr.reshape(-1) も同様に view を返す
  • C-order (行優先) がデフォルト、order="F" で列優先
  • 複数配列を結合して 1 次元化なら np.concatenate + reshape

flatten() と ravel() の違い

NumPy で多次元配列を 1 次元にする代表的な 2 つのメソッド:

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)    # (2, 3)

# 方法1: flatten(常にコピー)
b = a.flatten()
print(b)          # [1 2 3 4 5 6]
print(b.shape)    # (6,)
b[0] = 99
print(a[0, 0])    # 1 (元は変わらない)

# 方法2: ravel(可能なら view)
c = a.ravel()
print(c)          # [1 2 3 4 5 6]
c[0] = 99
print(a[0, 0])    # 99 (元も変わる!)
flatten()ravel()reshape(-1)
戻り値新しい配列(コピー)可能なら view可能なら view
メモリ使用2 倍同じ同じ
速度遅い(コピー発生)速い速い
元配列への影響なし(安全)あり(view 時)あり(view 時)
連続でない配列OKコピー発生コピー発生

reshape(-1) を使う方法

a = np.arange(24).reshape(2, 3, 4)
print(a.shape)     # (2, 3, 4)

# -1 は「残り全部」の意味
b = a.reshape(-1)
print(b.shape)     # (24,)
print(b)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

# 多次元 → 別の多次元も可能
c = a.reshape(6, 4)
d = a.reshape(-1, 4)   # 行は自動計算

C-order と F-order

1 次元化のとき、要素を取り出す順序を指定できます:

a = np.array([[1, 2, 3],
              [4, 5, 6]])

# C-order(行優先、デフォルト)
print(a.flatten(order='C'))
# [1 2 3 4 5 6]   ← 行を順に並べる

# F-order(列優先、Fortran)
print(a.flatten(order='F'))
# [1 4 2 5 3 6]   ← 列を順に並べる

# K-order(メモリレイアウトに従う)
print(a.flatten(order='K'))
# C 配列なら C 順、F 配列なら F 順

# A-order(C 連続なら C、それ以外は F)
print(a.flatten(order='A'))
order意味用途
C行優先(NumPy デフォルト)Python / C と相性良
F列優先(Fortran)MATLAB / 線形代数で使用
Kメモリ順最速
A連続性優先あまり使われない

np.concatenate と np.stack

複数の配列を結合して 1 次元化する場合:

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

# concatenate: 既存の軸に沿って結合
c = np.concatenate([a.ravel(), b.ravel()])
# [1 2 3 4 5 6 7 8]

# または直接 reshape
c = np.concatenate([a, b], axis=None)
# axis=None で自動 1 次元化
# [1 2 3 4 5 6 7 8]

# np.hstack / np.vstack
d = np.hstack([a, b])    # 横方向(axis=1)
# [[1 2 5 6]
#  [3 4 7 8]]
e = np.vstack([a, b])    # 縦方向(axis=0)
# [[1 2] [3 4] [5 6] [7 8]]

Python のリスト内包表記との比較

import numpy as np

a = np.arange(1_000_000).reshape(1000, 1000)

# 方法1: Python ループ(遅い)
flat_py = [x for row in a for x in row]
# 約 200ms

# 方法2: numpy.ravel(速い)
flat_np = a.ravel()
# 約 0.001ms (20万倍速い)

# 速度差の理由:
# - Python ループは要素ごとに Python オブジェクト化
# - NumPy はメモリレイアウトをそのまま使う(コピー不要なら)

メモリ効率の違い

import numpy as np
import sys

a = np.arange(10_000_000)
print(a.nbytes / 1024 / 1024, "MB")   # 76 MB

# flatten はコピー → 倍の 152 MB を使う
b = a.flatten()

# ravel は view → 元と同じメモリ
c = a.ravel()
print(c.base is a)   # True(同じデータを共有)
print(b.base)        # None(独立)

view と copy の判定

ravel / reshape が view を返せないケースもあるので確認方法:

a = np.arange(12).reshape(3, 4)

b = a.ravel()
print(b.base is a)   # True (view)

# 連続でない配列(slice 等で抜き出した場合)
c = a[:, ::2]   # 1 つ飛ばしで列を抜く
print(c.flags.c_contiguous)   # False

d = c.ravel()
print(d.base is a)   # False (コピーになった)

# 明示的に view を強制
e = c.reshape(-1)
# これはエラーになる場合あり

# 確実に view を取りたいなら .ravel(order='K')
f = c.ravel(order='K')

PyTorch / TensorFlow の同等関数

NumPyPyTorchTensorFlow
arr.flatten()tensor.flatten()tf.reshape(t, [-1])
arr.ravel()tensor.view(-1)同上
arr.reshape(-1)tensor.reshape(-1)同上
arr.flatten(order="F")非対応非対応

機械学習での典型例

# CNN の出力を全結合層に通すとき
batch_size, channels, h, w = 32, 64, 7, 7
features = np.random.randn(batch_size, channels, h, w)

# (32, 64, 7, 7) → (32, 3136) に変換
flattened = features.reshape(batch_size, -1)
print(flattened.shape)   # (32, 3136)

# 画像 1 枚のピクセルベクトル化
image = np.random.randint(0, 256, (28, 28), dtype=np.uint8)
vector = image.flatten()   # shape (784,)

FAQ

Q: flatten した結果を変更しても元配列が変わる
A: flatten はコピーなので変わらないはず。ravelreshape(-1) なら view なので変わる。

Q: 巨大配列で flatten がメモリエラー
A: コピーが必要なので元の 2 倍メモリを要求する。ravel を使うか、ジェネレータで chunk 処理に切替。

Q: 順序を維持したまま列優先で取り出したい
A: .flatten(order="F") または .T.ravel()(転置 → ravel)。