概要(NumPy 配列は「速く・簡潔に・大量データ」を扱うための土台)
NumPy 配列(ndarray)は、同じ型の要素を連続メモリに格納する「数値計算専用の配列」です。Pythonのリストより圧倒的に速く、ベクトル演算(配列全体を一気に計算)やブロードキャスト(形の違う配列同士の自動拡張)を使って、ループなしで短く書けます。初心者は「作る→形を知る→取り出す→計算する→形を変える→結合する」の流れと、dtype・shape・axis・broadcasting・“view と copy”の要点を押さえると、一気に扱える範囲が広がります。
基本の作成と情報確認(ここが重要)
配列の作成と dtype・shape・ndim の確認
import numpy as np
a = np.array([1, 2, 3]) # 1次元
b = np.array([[1, 2, 3], [4, 5, 6]]) # 2次元(行列)
print(a.dtype, a.shape, a.ndim) # int64 (例), (3,), 1
print(b.dtype, b.shape, b.ndim) # int64 (例), (2, 3), 2
Pythondtypeは「型」、shapeは「形(各次元の長さ)」、ndimは「次元数」です。最初に必ず確認すると、以降の操作が迷いません。
よく使う初期化(ゼロ・ワン・等間隔・乱数)
np.zeros((2, 3)) # 全ゼロ
np.ones((2, 3)) # 全ワン
np.arange(0, 10, 2) # 0,2,4,6,8(等差数列)
np.linspace(0.0, 1.0, 5) # 0.0〜1.0を5分割(等間隔)
np.random.rand(2, 3) # 0〜1一様乱数
np.random.randn(2, 3) # 標準正規乱数
Python「形」を先に決めてから初期化する癖をつけると、意図通りの配列が作れます。
取り出し・スライス・ブールマスク(安全で速い抽出)
インデックスとスライス(多次元は“行・列”で指定)
b = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(b[0, 1]) # 1行目2列(値: 2)
print(b[0, :]) # 1行目すべて → [1 2 3]
print(b[:, 1]) # 2列目すべて → [2 5 8]
print(b[0:2, 1:3]) # 1〜2行、2〜3列の部分行列
Python「行は先、列は後」が基本。コロン(:)で“その次元の全体”を指定します。
ブールマスク(条件で抽出)
a = np.array([10, 20, 15, 8, 30])
mask = a > 15
print(a[mask]) # 条件を満たす要素だけ → [20 30]
Python条件で配列をフィルタするのが最短で安全。複数条件は &(かつ)や |(または)を使います。
fancy indexing(インデックスの配列で取り出し)
a = np.array([10, 20, 30, 40])
idx = np.array([3, 0, 3, 1])
print(a[idx]) # → [40 10 40 20]
Python任意位置をまとめて取るときに便利です。
ベクトル演算・集計・axis(ループを書かない体を作る)
要素ごとの演算(ベクトル化)
x = np.array([1, 2, 3])
print(x * 2) # → [2 4 6]
print(x + 10) # → [11 12 13]
print(x ** 2) # → [1 4 9]
Python「配列に対してそのまま演算」できるのがNumPyの強み。forループより圧倒的に速く、短いです。
統計・集計と axis の意味
m = np.array([[1, 2, 3],
[4, 5, 6]])
print(m.sum()) # 全体の合計 → 21
print(m.sum(axis=0)) # 列方向の合計 → [5 7 9]
print(m.sum(axis=1)) # 行方向の合計 → [6 15]
print(m.mean(), m.std()) # 平均・標準偏差
Pythonaxisは「どの軸に沿って畳み込むか」。行方向集計なら axis=1、列方向なら axis=0。ここを理解すると一気に強くなります。
ufunc(ユニバーサル関数)で一括処理
x = np.array([0.0, 1.0, 2.0])
print(np.sin(x), np.log1p(x), np.sqrt(x))
Python数学関数はufuncとして“配列全体”に適用されます。
形を変える・結合する・コピーとビュー(落ちない設計)
reshape・ravel・transpose(形状操作)
a = np.arange(6) # [0 1 2 3 4 5]
print(a.reshape(2, 3)) # → 2x3
print(a.reshape(-1, 2)) # 列数固定で行数を自動(-1)
print(a.ravel()) # 1次元へ平坦化(ビューのことが多い)
print(a.reshape(2, 3).T) # 転置(行列の入れ替え)
Python-1は「自動計算」。ravelは“元データのビュー”になりやすく、変更が元に波及することに注意。
結合(縦・横)とスタック
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(np.concatenate([A, B], axis=0)) # 縦結合(行を増やす)
print(np.concatenate([A, B], axis=1)) # 横結合(列を増やす)
print(np.vstack([A, B])) # 縦スタック
print(np.hstack([A, B])) # 横スタック
Python形が合っていること(次元・長さ)を先に確認する習慣が事故を防ぎます。
view と copy(意図しない共有を避ける)
a = np.arange(5)
v = a.view() # 共有(ビュー)
c = a.copy() # 独立(コピー)
v[0] = 99
print(a) # → [99 1 2 3 4] 共有されている
c[1] = 77
print(a) # → [99 1 2 3 4] 影響しない
Python「後で元を変えたくない」なら必ず copy。ビューを意識できると、無駄コピーを減らして速く書けます。
ブロードキャストと線形代数(“形が違う”を自然に解く)
ブロードキャスト(形を自動拡張して計算)
M = np.array([[1, 2, 3],
[4, 5, 6]]) # 2x3
v = np.array([10, 20, 30]) # 1x3
print(M + v)
# 各行へ [10,20,30] を足す(列方向に自動拡張)
Python「次元末尾から合わせる」「長さ1の軸は伸びる」が直感。行に対して列ベクトルを足す場合は v を列ベクトル化(reshape)します。
u = np.array([100, 200]).reshape(2, 1) # 2x1
print(M + u) # 各行へ [100] と [200] を足す(行方向に拡張)
Python行列計算(@ 演算子・linalg)
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B) # 行列積
print(np.linalg.inv(A)) # 逆行列
print(np.linalg.solve(A, np.array([1, 0]))) # Ax=b を解く
print(np.linalg.eig(A)) # 固有値・固有ベクトル
Python数値線形代数は np.linalg が入り口。形の整合(内積の次元一致)を先に確認します。
実務パターン(前処理・標準化・クリッピング・高速化)
正規化・標準化・クリップ
x = np.array([10.0, 12.0, 9.0, 20.0])
# min-max 正規化(0〜1)
x_norm = (x - x.min()) / (x.max() - x.min())
# 標準化(平均0、分散1)
x_std = (x - x.mean()) / x.std()
# 外れ値のクリップ
x_clip = np.clip(x, 10.0, 15.0)
Python「先に配列へ落として、ベクトル化で一気に」前処理するのが最短で安全です。
欠損(NaN)への対応
y = np.array([1.0, np.nan, 3.0, np.nan])
print(np.isnan(y)) # 欠損の位置
print(np.nanmean(y)) # NaN を無視した平均
print(np.nan_to_num(y, nan=0.0)) # 欠損を0に置換
PythonNaNは「無視する系の関数(nanmean 等)」か「明示的に置換」で対処します。
pandas との往復(数値部分だけNumPyで高速化)
import pandas as pd, numpy as np
df = pd.DataFrame({"a": [1,2,3], "b": [4,5,6]})
arr = df[["a","b"]].to_numpy() # DataFrame → ndarray
df["sum"] = arr.sum(axis=1) # ndarrayの集計結果を戻す
Python重い計算は NumPy、周辺の入出力は pandas で、役割分担すると速くて読みやすいです。
例題で身につける(定番から一歩先まで)
例題1:2次元配列から列合計・行平均を出す
import numpy as np
M = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
col_sum = M.sum(axis=0) # → [12 15 18]
row_mean = M.mean(axis=1) # → [2. 5. 8.]
print(col_sum, row_mean)
Python例題2:ブールマスクで閾値以上を抽出し、クリップ
import numpy as np
x = np.array([10, 25, 18, 5, 33, 12])
high = x[x >= 20] # → [25 33]
x_clipped = np.clip(x, 10, 20) # 10〜20に丸める
print(high, x_clipped)
Python例題3:ブロードキャストで列ごとにオフセット加算
import numpy as np
M = np.array([[1, 2, 3],
[4, 5, 6]])
offset = np.array([10, 20, 30]) # 1x3
print(M + offset)
Python例題4:形を変えて縦結合・横結合
import numpy as np
a = np.arange(6).reshape(2, 3) # [[0,1,2],[3,4,5]]
b = (np.arange(6) + 100).reshape(2, 3)
print(np.vstack([a, b])) # 4x3
print(np.hstack([a, b])) # 2x6
Pythonまとめ
NumPy 配列の核は「同型・連続メモリ・ベクトル演算」で、リストより速く・短く・安全に数値処理が書けます。作成したら dtype・shape・ndim を確認し、抽出はインデックス/スライス/ブールマスク、計算はベクトル化と ufunc、集計は axis の意味を正しく理解する。reshape・ravel・転置で形を自在に扱い、結合は vstack/hstack/concatenate。view と copy を区別して意図しない共有を避け、ブロードキャストで“形が違う”計算を自然に解く。最後に「先に配列へ落として一気に処理する」癖がつけば、初心者でも実務で通用するスピードと安定性を手に入れられます。
