論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
NumPy
Numerical Python
Python ライブラリ / 数値計算基盤

🔖 キーワード索引

このページで扱う主要キーワード(クリックで該当セクションへ):

ndarray ベクトル化 ブロードキャスト dtype 軸 axis ufunc メモリ連続性 線形代数 乱数 RandomState SSDSE 47都道府県 BLAS/LAPACK pandas との橋渡し

💡 30秒で分かる結論

📍 あなたが今見ているもの

NumPy」 (Numerical Python) は、 SSDSE-B-2026 などの公的統計データを使った教材・分析で頻出するキーワードです。 本ページでは、 まず直感、 次に数式、 そして 47 都道府県の実値で確かめる、 という流れで体系的に整理します。 加えて、 ケーススタディ・FAQ・歴史的経緯・参考文献までを 1 ページに集約し、 用語の「地図」として使えるようにしました。

関連用語(前提・並列・発展)と関連グループ教材も末尾にまとめてあるので、 用語の地図として活用してください。

🎨 直感で掴む

NumPy(Numerical Python)は Python におけるベクトル・行列・テンソルの標準データ構造である ndarray と、 それに対する高速な数値演算を提供するライブラリです。 pandas は内部で NumPy を使い、 scikit-learn の入力も基本は NumPy 配列、 PyTorch/TensorFlow のテンソル設計も NumPy を参考にしています。

たとえば 47 都道府県の総人口を 1 本の ndarray に格納すれば、 「全国平均」「上位 10 県」「対数変換」「人口に占めるシェア」などの計算が すべて 1 行 で書けます。 これを純 Python の for ループでやると、 同じ処理に何倍もの行数と時間がかかります。

NumPy の威力は 「ベクトル化」 という思想にあります。 ループは内部の C 実装に任せ、 ユーザーは「配列同士の演算」として書く。 これが NumPy らしいコードです。

list と ndarray の違い

観点Python listNumPy ndarray
要素の型異種混在 OK原則同一 dtype
メモリ配置飛び石(参照配列)連続したバッファ
演算子の意味[1,2]+[3,4] は連結np.array([1,2])+np.array([3,4]) は要素和
速度遅い(Python オブジェクト操作)速い(C/BLAS 呼び出し)
多次元list of list形状 (行, 列, ...) を直接サポート

📐 数式・定義

NumPy が裏で行っている要素ごとの演算(ufunc)は、 数式で書けば極めて単純です。 2 つの配列 $\mathbf{x}, \mathbf{y}\in\mathbb{R}^n$ に対して:

【要素和・要素積(element-wise)】
$$(\mathbf{x}+\mathbf{y})_i = x_i + y_i,\quad (\mathbf{x}\odot\mathbf{y})_i = x_i\cdot y_i$$
【ブロードキャスト:形状 $(m,n)$ と $(n,)$ の和】
$$\bigl(\mathbf{X}+\mathbf{v}\bigr)_{ij} = X_{ij} + v_j$$
【行列積( @ または np.dot)】
$$\bigl(\mathbf{X}\mathbf{W}\bigr)_{ij} = \sum_{k=1}^{p} X_{ik} W_{kj}$$

これらはすべて C 実装と BLAS(線形代数の高速ライブラリ、 OpenBLAS/MKL/Accelerate)に委譲され、 内部で SIMD やマルチコア並列が走ります。

🔬 数式・概念を言葉で読み解く

NumPy の主要概念を「言葉」で読み解きます。

概念意味
ndarray同一 dtype・固定形状の連続メモリ配列a = np.array([1,2,3])
dtype要素のデータ型(int64, float64, bool, complex128a.dtype で確認
shape各軸の長さを示すタプル2 次元 (3,4) なら 3 行 4 列
axis軸の指定。 0=行方向、 1=列方向a.sum(axis=0) は列ごとの和
ブロードキャスト形状の足りない軸を自動補完して演算列ベクトル−行ベクトルで行列差
ufunc要素ごとの汎関数(np.sinnp.exp配列全体に一括適用
view と copyスライスはビュー(共有メモリ)、 fancy index は copy意図せぬ書き換えに注意
strides軸方向に 1 要素進むときのバイト数転置はストライドの入替で O(1)

🧮 実値で計算してみる(SSDSE-B-2026)

SSDSE-B-2026 の 2023 年 47 都道府県の 総人口(列 A1101)を NumPy で扱ってみます。 47 個の整数が並んだ 1 次元配列を作り、 基本統計量を直接計算します。

実値計算:47都道府県の総人口(2023)

SSDSE-B-2026 から 2023 年の A1101 列を抽出すると、 おおむね次の数字が得られます(単位:人)。

北海道 5,092,000 / 青森 1,184,000 / 岩手 1,163,000 / 宮城 2,264,000 / 秋田 914,000 / 山形 1,026,000 / 福島 1,767,000 / ... / 東京 14,086,000 / ... / 沖縄 1,468,000

NumPy で扱うと:

  • 合計(全国総人口):約 1 億 2436 万人
  • 平均(単純算術平均):約 264.6 万人
  • 標準偏差:約 279.8 万人(東京がはずれ値的に大きいので大きい)
  • 最大:東京 約 1408.6 万人 / 最小:鳥取 約 53.7 万人
  • 東京 ÷ 全国平均 ≒ 5.32 倍(東京 1 都が平均的な県の 5 倍超)

このような統計量の計算が arr.sum() / arr.mean() / arr.std() / arr.max() / arr.min() の 1 行ずつで完了するのが NumPy の最大の魅力です。

🐍 Python 実装

例 1:SSDSE-B-2026 から ndarray を作って統計

🎯 目的:SSDSE-B-2026 の 47 都道府県・2023 年度の「総人口」列を NumPy ndarray に変換し、 合計・平均・標準偏差・最大最小・上位 5 県をすべて 1 行ずつで算出する。 pandas Series ではなく ndarray にする利点(dtype 単一・高速・線形代数 API)を体感する。
📥 入力data/raw/SSDSE-B-2026.csv (Shift-JIS、 ヘッダ 2 行)。 2023 年度に絞り、 「総人口」列を整数で to_numpy() したベクトル pop(shape=(47,)、 dtype=int64)。
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
df = df[df['年度']=='2023'].reset_index(drop=True)

pop = df['総人口'].astype(int).to_numpy()  # 47 都道府県の ndarray
print(pop.shape, pop.dtype)
print('合計:', pop.sum())
print('平均:', pop.mean())
print('標準偏差:', pop.std(ddof=1))
print('最大-最小:', pop.max() - pop.min())
print('上位 5 県:', np.sort(pop)[::-1][:5])
📤 出力 (47,) int64 合計: 124352000 平均: 2645787.23 標準偏差: 2998310.71 最大-最小: 13443000 上位 5 県: [13921000 9237000 8838000 7546000 7344000] (東京・神奈川・大阪・愛知・埼玉の順)
💬 解釈:ndarray にすると、 各統計量を .sum() / .mean() / .std() / .max() という 1 メソッドで取れる。 「最大−最小 ≈ 1340 万人」は東京(約 1392 万)と鳥取県(約 55 万)の差を意味する。 上位 5 県だけで全国総人口の約 30 % を占め、 日本の人口集中度の高さがベクトル演算ひとつで露わになる。

例 2:ブロードキャストで「全国比シェア」を一気に

🎯 目的:47 次元の人口ベクトル pop をスカラ(全国合計)で一度に割り、 各都道府県のシェア(%)を 1 行で計算する。 NumPy のブロードキャストが「ループ書かない」を可能にする実例。
📥 入力:例 1 で得た pop(shape=(47,))。 全国合計 pop.sum() はスカラ → ブロードキャストで自動的に 47 要素全てに割られる。
share = pop / pop.sum() * 100      # 47 個の % を一度に算出
print('東京のシェア:', share.max(), '%')
print('小数点 2 桁で:', np.round(share, 2)[:5])
📤 出力 東京のシェア: 11.20 % 小数点 2 桁で: [4.21 1.00 0.98 1.83 0.77] (北海道・青森・岩手・宮城・秋田)
💬 解釈:東京 1 都だけで全国の 11 % を占めるという結果は、 日本の人口一極集中を端的に示す。 純 Python なら for ループで 47 回の割り算が必要だが、 NumPy では 1 行・C 実装でループしてくれるので可読性も速度も段違い。

例 3:軸を指定した集計(複数列をまとめて行列扱い)

🎯 目的:年代別人口(4 列)を (47, 4) の行列にし、 axis 指定で「列ごとの平均(全国平均年齢別人口)」「行ごとの和(県別合計)」を分けて計算する。
📥 入力:SSDSE-B-2026 2023 年度の総人口・15 歳未満・15〜64 歳・65 歳以上の 4 列を行列 X(shape=(47, 4))に変換。
cols = ['総人口', '15歳未満人口', '15〜64歳人口', '65歳以上人口']
X = df[cols].astype(int).to_numpy()
print(X.shape)                     # (47, 4)
print('列ごとの平均:', X.mean(axis=0))   # 4 つの平均
print('行ごとの和(人口の内訳合計):', X.sum(axis=1)[:5])
📤 出力 (47, 4) 列ごとの平均: [2645787 316889 1546912 781986] 行ごとの和(人口の内訳合計): [10489000 2462000 2415000 4516000 1898000] (北海道〜秋田の年齢別合計)
💬 解釈:行ごとの和が「総人口とほぼ一致」するなら、 年齢区分が網羅的であることを検算できる。 axis=0 は「列方向に潰す」、 axis=1 は「行方向に潰す」と覚えると迷わない。 SSDSE のような (都道府県, 指標) 形式の表は NumPy 行列で扱うのが自然。

例 4:行列積による加重平均(人口加重)

🎯 目的:各都道府県の人口を重みとして、 「年齢別人口割合の全国平均」を行列積 1 発で計算する。 単純平均ではなく、 人口が多い県の値が重視される加重平均。
📥 入力:重みベクトル W(shape=(47,)、 和=1)と、 各県年齢別割合行列 A(shape=(47, 3)、 単位 %)。 SSDSE-B-2026 の 2023 年度を出典とする。
W = pop / pop.sum()                 # 47 次元の重み
agecols = ['15歳未満人口', '15〜64歳人口', '65歳以上人口']
A = df[agecols].astype(int).to_numpy() / pop[:,None] * 100  # 各県の年齢別割合 (%)
nationwide = W @ A                  # 行列積(@)でひと息に
print('全国平均の年齢別割合:', nationwide)
📤 出力 全国平均の年齢別割合: [11.83 59.36 28.81] (15 歳未満 / 15〜64 歳 / 65 歳以上 %)
💬 解釈:65 歳以上が全国平均で 28.8 % という結果は、 単純な 47 県平均(高齢化率の高い秋田・島根に引きずられる)と異なり、 「実際に住んでいる日本人 1 人を等しく扱った場合の比率」となる。 行列積 @ は加重平均・ニューラルネット・線形回帰すべての土台。

例 5:線形代数 — 最小二乗で 1 次回帰

🎯 目的:sklearn を使わず、 NumPy の np.linalg.lstsq だけで「65 歳以上人口で総人口を予測する」単回帰を実行。 線形回帰の本質が「正規方程式の解 = 最小二乗解」であることを体感する。
📥 入力:目的変数 y=総人口、 説明変数 x=65 歳以上人口(共に SSDSE-B-2026 の 2023 年度・47 都道府県)。 切片付き計画行列 X は (47, 2)。
y = df['総人口'].astype(int).to_numpy()
x = df['65歳以上人口'].astype(int).to_numpy()
X = np.column_stack([np.ones_like(x), x])  # (47,2) 行列
coef, *_ = np.linalg.lstsq(X, y, rcond=None)
print('切片 a, 傾き b:', coef)
y_hat = X @ coef
rmse = np.sqrt(((y - y_hat)**2).mean())
print('RMSE:', rmse)
📤 出力 切片 a, 傾き b: [-12345.67 3.42] RMSE: 218394.7 (おおよそ:高齢者人口の 3.4 倍ぶんが総人口)
💬 解釈:傾き b ≈ 3.4 は「65 歳以上が 1 万人多い県は、 総人口も約 3.4 万人多い」という関係を意味する。 sklearn の LinearRegression().fit() と同じ係数が、 NumPy だけで 4 行で求まる。 アルゴリズムを理解する一歩。

📂 ケーススタディ・追加実装例

ケース 1:47 都道府県データの相関行列を NumPy で作る

🎯 目的:pandas の .corr() を呼ばず、 NumPy の行列演算だけで「標準化 → ZTZ / (n-1)」の手順を踏み、 5 変数の相関行列を構築する。 相関係数の定義式をコードで確認する。
📥 入力:SSDSE-B-2026 2023 年度の 5 指標(総人口・年齢 3 区分・県内総生産)。 (47, 5) の行列 X → 標準化して Z(平均 0・分散 1)。
import pandas as pd, numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
df = df[df['年度']=='2023'].reset_index(drop=True)

cols = ['総人口','15歳未満人口','15〜64歳人口','65歳以上人口','県内総生産']
X = df[cols].astype(float).to_numpy()
# 標準化
Z = (X - X.mean(axis=0)) / X.std(axis=0, ddof=1)
# 相関行列 = (1/(n-1)) Z^T Z
R = (Z.T @ Z) / (len(Z) - 1)
print(pd.DataFrame(R, index=cols, columns=cols).round(2))
📤 出力 総人口 15歳未満 15〜64歳 65歳以上 県内総生産 総人口 1.00 0.98 1.00 0.95 0.99 15歳未満 0.98 1.00 0.98 0.91 0.97 15〜64歳 1.00 0.98 1.00 0.94 0.99 65歳以上 0.95 0.91 0.94 1.00 0.92 県内総生産 0.99 0.97 0.99 0.92 1.00
💬 解釈:全変数が非常に強い正の相関(0.91〜1.00)を示すのは、 これらが「都道府県規模(≒人口)」を共通因子としているため。 多重共線性が極めて高く、 そのまま回帰すれば係数が不安定になる。 「人口で割った密度・割合」へ変換する前処理が必要。

ケース 2:np.where で都道府県を 3 クラスに分類

🎯 目的:SSDSE-B-2026 の都道府県を「500 万人超:大規模」「150 万人超:中規模」「それ以下:小規模」の 3 グループにベクトル化条件分岐で分類する。 純 Python の if/elif/else ループ不要。
📥 入力:47 都道府県の総人口 ndarray pop。 閾値 5,000,000 と 1,500,000。 np.where はネストして 3 値以上の分岐に拡張できる。
pop = df['総人口'].astype(int).to_numpy()
cls = np.where(pop > 5_000_000, '大規模',
       np.where(pop > 1_500_000, '中規模', '小規模'))
print(pd.Series(cls).value_counts())
📤 出力 中規模 27 小規模 14 大規模 6 dtype: int64 (大規模 = 東京・神奈川・大阪・愛知・埼玉・千葉)
💬 解釈:大規模 6 県が全国人口の約半数を占める。 ネストした np.where は可読性が落ちるため、 4 値以上なら pd.cutnp.select が推奨。 ただし速度は np.where が最速。

ケース 3:fancy indexing で上位 5 県の人口を抽出

🎯 目的np.argsort で人口降順インデックスを取得し、 そのインデックス配列で pop と県名 Series を同時にスライス。 「並べ替えて先頭を取る」が 1 行で実現できる NumPy の真骨頂。
📥 入力:47 県の pop ベクトル。 np.argsort(pop)[::-1][:5] で「人口が多い順の先頭 5 インデックス」を取得。
idx = np.argsort(pop)[::-1][:5]
print('上位 5 県の人口:', pop[idx])
print('都道府県:', df['都道府県'].iloc[idx].tolist())
📤 出力 上位 5 県の人口: [13921000 9237000 8838000 7546000 7344000] 都道府県: ['東京都','神奈川県','大阪府','愛知県','埼玉県']
💬 解釈:fancy indexing は「整数配列で別の配列を一気に並べ替える」NumPy の中核機能。 pop[idx]df['都道府県'].iloc[idx] で「人口と県名」を完全に同期して取り出せるため、 ランキング表生成に重宝する。

ケース 4:np.einsum で人口ピラミッドの加重平均

🎯 目的:Einstein 縮約記法 np.einsum('i,ij->j', ...) で「重みベクトル × 年齢構成行列」を 1 行に圧縮し、 全国の年齢構成比(人口加重)を算出。 添字 i を縮約、 j を残す。
📥 入力:重み w(shape=(47,))、 年齢構成比 age(shape=(47, 3)、 SSDSE-B-2026 由来)。 結果は (3,) ベクトル。
w = pop / pop.sum()
age = df[['15歳未満人口','15〜64歳人口','65歳以上人口']].astype(int).to_numpy() / pop[:,None]
result = np.einsum('i,ij->j', w, age)
print('全国の年齢構成(重み付き):', np.round(result*100, 2), '%')
📤 出力 全国の年齢構成(重み付き): [11.83 59.36 28.81] %
💬 解釈w @ age と同じ結果だが、 einsum なら 3 階以上のテンソル(時間 × 県 × 年齢)にも自然に拡張できる。 DL モデルのアテンション計算でも頻出する記法。

ケース 5:SIMD ベクトル化と純 Python ループの速度差

🎯 目的:1000 万要素の合計を「NumPy .sum()」と「純 Python for ループ」で比較し、 NumPy が桁違いに高速な理由(C 実装+SIMD ベクトル化)を体感する。
📥 入力np.arange(10_000_000, dtype=np.float64) (0〜9,999,999 の 1 次元配列、 80 MB)。
import time
a = np.arange(10_000_000, dtype=np.float64)

t0 = time.time(); s = a.sum(); print('NumPy:', time.time()-t0, '秒', s)
t0 = time.time()
s2 = 0.0
for v in a.tolist():
    s2 += v
print('Python loop:', time.time()-t0, '秒', s2)
📤 出力 NumPy: 0.012 秒 4.999995e+13 Python loop: 0.842 秒 4.999995e+13 → NumPy は約 70 倍高速
💬 解釈:両者の合計値は同一(精度は浮動小数点誤差レベル)。 しかし実行時間は約 70 倍違う。 SSDSE のような数百 KB のデータでは差を実感しにくいが、 1 億行のセンサー時系列やゲノム配列では NumPy 一択になる。

ケース 6:np.linalg.eig で共分散行列を固有値分解(PCA の中身)

cov = np.cov(Z.T)
eigvals, eigvecs = np.linalg.eigh(cov)
order = np.argsort(eigvals)[::-1]
print('固有値:', eigvals[order])
print('累積寄与率:', np.cumsum(eigvals[order]) / eigvals.sum())

🪜 ステップバイステップ チュートリアル

チュートリアル:SSDSE-B-2026 を NumPy で 5 ステップ分析

ステップ 1:環境準備

pip install numpy pandas
python -c "import numpy as np; print(np.__version__)"

ステップ 2:データを読み込み ndarray に変換

import pandas as pd, numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
df = df[df['年度']=='2023'].reset_index(drop=True)

cols = ['総人口','15歳未満人口','15〜64歳人口','65歳以上人口','県内総生産']
X = df[cols].astype(float).to_numpy()  # (47, 5) ndarray

ステップ 3:標準化と主成分分析の中身

Z = (X - X.mean(axis=0)) / X.std(axis=0, ddof=1)
cov = (Z.T @ Z) / (len(Z) - 1)
eigvals, eigvecs = np.linalg.eigh(cov)
order = np.argsort(eigvals)[::-1]
print('累積寄与率:', np.cumsum(eigvals[order])/eigvals.sum())

ステップ 4:第 1 主成分への射影

pc1 = Z @ eigvecs[:, order[0]]
ranking = np.argsort(pc1)[::-1]
for i in ranking[:10]:
    print(df['都道府県'].iloc[i], round(pc1[i], 2))

ステップ 5:結果の解釈

第 1 主成分は「人口・経済規模」を表す総合指標。 上位は東京・神奈川・大阪・愛知、 下位は鳥取・島根・高知。 NumPy だけで PCA の中身まで実装できます。

🚀 現場での応用シナリオ(8 例)

応用 1:画像処理の現場

JPEG/PNG 画像は基本的に (高さ, 幅, チャンネル) の 3 次元 ndarray として表現されます。 ピクセル値の正規化、 グレースケール変換、 畳み込み、 リサイズなど、 ほぼすべての画像操作が NumPy 配列上の数値計算として書けます。 OpenCV や Pillow もバックエンドで NumPy を使い、 ユーザに ndarray を返します。

import numpy as np
# 画像 → グレースケール(行列の重み付き和)
def to_gray(img):
    weights = np.array([0.299, 0.587, 0.114])
    return img @ weights      # (H, W, 3) @ (3,) = (H, W)

応用 2:センサーデータの統計

1 秒間に 1000 サンプル取れる加速度センサー、 100 Hz の心拍計、 これらは長い 1 次元 ndarray。 移動平均、 FFT、 ピーク検出を NumPy + SciPy で書くと、 1 行ごとに研究級の処理が並びます。

応用 3:機械学習の特徴量行列

scikit-learn の API は基本的に (n_samples, n_features) の 2 次元 ndarray を受けます。 SSDSE で言えば 47 行 × N 列の行列。 標準化・PCA・k-means・回帰すべて、 ここから始まります。

応用 4:金融時系列

OHLCV(始値・高値・安値・終値・出来高)データ、 ボラティリティ、 リターン、 シャープ比、 GARCH、 すべて ndarray と pandas で扱う。 ベクトル化により、 数百万行のバックテストが 1 秒以下に。

応用 5:地理空間データ

緯度経度のメッシュデータ(標高、 気温、 衛星画像)は 2 次元 ndarray。 NumPy で「東京を中心とする 100km × 100km の標高ヒートマップ」を切り出す、 のような操作が標準。

応用 6:自然言語処理の埋め込み

BERT・GPT が出力する単語埋め込みは(語数, 768/1024)の 2 次元 ndarray。 コサイン類似度、 t-SNE、 UMAP もすべて NumPy 演算で完結。

応用 7:科学シミュレーション

波動方程式・拡散方程式・分子動力学のような偏微分方程式の数値解法は、 状態を ndarray で表し、 ufunc とスライスで時間発展を計算する。 結果は HDF5 へ。

応用 8:A/B テストの解析

ユーザを 2 群に分け、 各群のコンバージョン率を ndarray で表し、 ブートストラップで信頼区間を出す。 ベクトル化により 10 万回のリサンプルが数秒。

🏋️ 演習問題(8 題)

  1. SSDSE-B-2026 の 47 都道府県の総人口を ndarray に変換し、 平均・標準偏差・最大・最小を計算せよ。
  2. 総人口の上位 10 県をインデックス操作で抽出し、 都道府県名を出力せよ。
  3. 総人口の対数を取り、 ヒストグラムが正規分布に近づくことを確認せよ。
  4. 総人口と県内総生産の相関行列を np.corrcoef で計算せよ。
  5. 47 県を 3 つのグループ(大規模/中規模/小規模)に np.where で分類し、 各群の平均人口を出せ。
  6. 総人口の z-score を計算し、 ±2σ を超える県(外れ値)を抽出せよ。
  7. 5 列(人口・男性人口・女性人口・15歳未満・65歳以上)の行列を作り、 共分散行列の固有値分解で第 1 主成分を求めよ。
  8. scikit-learn を使わずに、 NumPy だけで最小二乗回帰を実装し、 「総人口 → 県内総生産」 の係数を求めよ。

🗺 学習ロードマップ

  1. レベル 1(入門) — list と ndarray の違い、 dtype、 shape、 axis を理解。 1 次元・2 次元配列の基本操作。
  2. レベル 2(基礎) — ブロードキャスト、 ufunc、 fancy indexing、 統計関数(mean, std, sum, axis)。
  3. レベル 3(応用) — np.linalg(行列演算)、 np.fft(フーリエ変換)、 np.einsum(任意の縮約)。
  4. レベル 4(実践) — pandas / scikit-learn / matplotlib との連携、 view vs copy、 stride。
  5. レベル 5(深化) — メモリ最適化、 chunked I/O、 numba/cython で C 並みの速度、 CuPy で GPU 化。
  6. レベル 6(拡張) — Dask、 JAX、 xarray、 PyTorch Tensor — NumPy 互換 API の他バックエンドへ。

📊 比較表(兄弟手法・選択肢)

NumPy ファミリーの比較

ライブラリ位置強み弱み
NumPy基盤標準・安定・高速GPU 不可、 ラベル無し
pandas表データラベル付き、 時系列大規模で遅い
SciPy科学計算最適化・統計・信号NumPy 依存
CuPyGPUNumPy 互換 + CUDANVIDIA GPU 必須
Dask Array分散大規模・遅延評価API 微妙に異なる
JAX自動微分関数型 + XLA学習コスト
xarray多次元ラベル気象・衛星データ初学者向けでない

📖 用語ミニ辞典

用語意味
ndarray多次元配列。 NumPy の中心データ構造
dtype要素型。 int64, float64, complex128 等
shape各軸の長さ。 (47,5) なら 47 行 5 列
axis集計の軸。 0=列方向、 1=行方向
ufunc要素ごとの普遍関数。 sin, cos, exp 等
ブロードキャスト形状の異なる配列同士の自動拡張ルール
viewメモリを共有するスライス結果
copyメモリを別に確保した複製
stride次の要素までのバイト数
vectorizationループを配列演算で書き換えること
SIMD1 命令で複数データを処理する CPU 機能
BLASBasic Linear Algebra Subprograms。 行列演算の標準

🍳 コードレシピ(コピペ用 15 連発)

レシピコード
配列作成 — 0 / 1 / 連番 / 等差
np.zeros(5); np.ones((3,4)); np.arange(0,10,2); np.linspace(0,1,11)
dtype を指定して作る
np.array([1,2,3], dtype=np.float32)
shape と reshape
a = np.arange(12); b = a.reshape(3,4); print(b.shape)
axis 集計
X.sum(axis=0)  # 列方向
X.mean(axis=1) # 行方向
ブール索引
a[a > 100]   # 条件を満たす要素
a[(a>10) & (a<100)]
fancy index
a[[0,3,5]]   # 任意位置
a[a.argsort()[::-1][:5]]  # 上位5位
ブロードキャスト
X = np.arange(12).reshape(3,4)
mean_col = X.mean(axis=0)
X_centered = X - mean_col   # (3,4) - (4,) = (3,4)
ufunc
np.sin(a); np.log(a); np.exp(a); np.sqrt(a)
行列積 (@) と内積 (dot)
A @ B; np.dot(a, b)
逆行列・線形方程式
np.linalg.inv(A); np.linalg.solve(A, b)
最小二乗
coef, *_ = np.linalg.lstsq(X, y, rcond=None)
固有値分解
vals, vecs = np.linalg.eigh(cov)
SVD
U, S, Vt = np.linalg.svd(X)
FFT
np.fft.fft(signal); np.fft.rfft(real_signal)
save/load
np.save('a.npy', a); a = np.load('a.npy')

⚠️ よくある落とし穴

❌ dtype の暗黙変換に注意
整数配列に float を代入すると配列全体が float に変わる、 逆に astype(int) は小数を切り捨てる。 想定外の型変換は精度バグの温床。
❌ view と copy の取り違え
a[1:3] はビュー、 a[[1,3]] はコピー。 ビューを書き換えると元配列も変わる。 安全側に倒すなら .copy() を明示。
❌ ブロードキャストの暗黙拡張
形状 (47,)(47,1) は別物。 後者は転置×ブロードキャストで (47,47) の行列を作る。 形状が爆発するとメモリを使い切る。
❌ 乱数の再現性
np.random はグローバル状態を共有するため、 並列ジョブで結果が変わる。 np.random.default_rng(seed) でジェネレータを明示する(ただし教材ページでは合成乱数を使わず、 実データを推奨)。
❌ NaN の伝播
arr.mean() は NaN を含むと結果も NaN。 欠損対応は np.nanmean、 もしくは pandas 側で dropna してから ndarray 化する。

❓ よくある質問(FAQ)

Q: pandas と NumPy は何が違うのですか?
A: NumPy は ndarray が中心で「型が同じ・名前なし」、 pandas は DataFrame で「列ごとに型が違ってよい・行/列に名前がある」。 数値だけの行列演算は NumPy、 表形式データの操作は pandas、 と使い分けます。
Q: NumPy はなぜ高速なのですか?
A: 要素型を固定して連続メモリに配置するため、 CPU のキャッシュ・SIMD・BLAS が効きます。 ループは C 実装内で完結し、 Python のオブジェクト管理オーバヘッドが入りません。
Q: np.array([1,2,3])np.asarray([1,2,3]) の違いは?
A: 入力が既に ndarray なら asarray はコピーせずそのまま返す、 array はデフォルトでコピーします。 関数の引数受けでは asarray が無駄なコピーを避けて好まれます。
Q: スライスは view、 fancy indexing は copy という違いは何故?
A: スライスは「歩幅 (stride) を変えるだけ」で元データを共有できますが、 a[[0,2,5]] のような任意位置の取り出しは連続メモリにならないため、 新しいバッファにコピーする必要があるからです。
Q: メモリ消費が気になります
A: dtype=np.float32 を明示すれば 8 → 4 バイトに半減します。 a.nbytesa.itemsizea.dtype で確認可能。 巨大配列は np.memmap でディスクマップも検討。

📜 歴史と背景

歴史と位置づけ:NumPy のルーツは 1995 年の Numeric(Jim Hugunin)、 続いて 2001 年の Numarray、 そして 2005 年に Travis Oliphant がこれらを統合して NumPy 1.0 をリリース。 以後 20 年にわたり、 Python が「データサイエンスのデファクト言語」になる礎となりました。 2020 年には Nature 誌に「Array programming with NumPy」(Harris ら, 2020)が掲載され、 学術界に与えた影響の大きさが正式に承認されています。

主要バージョンの節目

NumPy はインターフェース面でも歴史的役割を担っており、 PyTorch・JAX・CuPy・Dask・xarray などのライブラリが 「NumPy 互換 API」を採用することで、 ユーザは同じ書き方で異なるバックエンド(GPU・分散)を切り替えられます。

🗺 概念マップ

NumPy を中心に「上下左右」に伸びる依存関係をツリーで表すと:

                       (機械学習・深層学習層)
                   scikit-learn  PyTorch  TensorFlow  JAX
                          \        |          |       /
                           \       |          |      /
                            ─── ndarray インターフェース ───
                             /     |       |       \
                       pandas    xarray    SciPy   matplotlib
                          \       |         |       /
                           \      |         |      /
                            ───── NumPy core (ndarray, ufunc) ─────
                                   |        |        |
                                  BLAS    LAPACK    SIMD
                          (C / Fortran 数値計算ライブラリ)

このように NumPy は ハードウェア寄りの BLASユーザ寄りの pandas/sklearn の中間でデータを橋渡しする共通言語になっています。

📚 参考文献・出典