この記事ではNumPyの概要と重要性、ndarrayによる多次元配列処理やブロードキャストなどの特徴を整理し、機械学習で数値計算を高速化できる理由を解説。インストール/インポート手順から、append・where・arange・mean・reshape・dot・random等の基本関数まで学べ、数値計算や配列操作のつまずきを解消できます。
目次
NumPyとは何か(Pythonの数値計算ライブラリの位置づけ)

NumPy(ナンパイ)は、Pythonで数値計算を行うための代表的なライブラリです。Python標準のリストでも計算はできますが、データ量が増えたり、行列・統計などの処理が必要になったりすると、可読性・速度・機能面で限界が見えやすくなります。そこで登場するのがNumPyで、Pythonに「高速で扱いやすい配列計算」の土台を提供し、データ分析や機械学習の入り口としても頻繁に登場します。
NumPyの概要とできること
python numpyの中心にあるのは、多次元配列を表すndarrayというデータ構造です。ndarrayを使うことで、数値データを「まとまり(配列)」として効率よく保持し、まとめて計算できます。これにより、ループを多用した手書き処理よりも、シンプルで高速なコードを書きやすくなります。
NumPyでできることは多岐にわたりますが、まず押さえたいのは次のような領域です。
- 配列(ベクトル・行列)を作成し、形状を揃えたデータとして扱える
- 要素ごとの四則演算や、まとめて適用する計算(例:全要素に同じ処理)
- 集計(合計・平均・最大・最小など)や基本的な統計処理の下地
- 線形代数(ベクトル・行列計算)の基礎となる操作が可能
つまりNumPyは、「数値を大量に扱うPythonプログラム」を実務的な速度と記述で成立させるための基盤です。データを“配列”として持てるだけでなく、計算を“配列の演算”として書ける点が、Pythonの数値計算における大きな転換点になります。
なぜNumPyが重要視されるのか(データ分析・機械学習の基盤)
NumPyが重要視される理由は、単に「便利なライブラリ」だからではありません。データ分析や機械学習では、数値データを大きな行列として扱い、繰り返し計算する場面が多くあります。ここで求められるのは、次の2点です。
- 計算が速いこと:大量データの前処理や特徴量計算、行列演算などを現実的な時間で終える必要がある
- データを一貫した形で扱えること:配列の形状(行数・列数)を保ちながら、集計・変換・計算を積み重ねる必要がある
python numpyはこれらを支える「共通言語」のような役割を担います。数値データをndarrayに揃えることで、処理の入力と出力が整理され、後続の分析工程へスムーズにつなげやすくなります。
また、機械学習の基本は「データ(行列)×パラメータ(ベクトル/行列)を計算し、誤差をもとに更新する」という形で表現されることが多く、内部では配列計算が中心です。そのため、NumPyを理解しておくことは、単なる文法知識ではなく、データ分析・機械学習の計算の考え方を身につける近道にもなります。
NumPyの主要な特徴

python numpy が多くの現場で選ばれる理由は、「速い」「扱いやすい」「コードが簡潔になる」という実用面の強さにあります。ここでは、NumPyを使ううえで特に重要な3つの特徴(ベクトル化計算、ndarray、ブロードキャスト)に絞って整理します。
高速なベクトル化計算で処理を加速できる
NumPyの大きな魅力は、Pythonのforループで1要素ずつ処理する代わりに、配列全体に対して一括で計算(ベクトル化)できる点です。これにより、処理速度が大幅に向上し、コードも短く読みやすくなります。
ベクトル化が高速なのは、NumPyが内部で最適化された低レベルの実装(C言語など)を使って計算し、Pythonのループによるオーバーヘッドを避けられるためです。大量データを扱うデータ分析や前処理で、体感できるほど差が出ます。
import numpy as np
x = np.array([1, 2, 3, 4, 5])
# 配列全体に対して一括で演算できる(ベクトル化)
y = x * 2 + 1
print(y) # [ 3 5 7 9 11]このように、python numpy では「要素ごとに同じ計算を適用する」ケースを自然に表現でき、速度と可読性を両立できます。
多次元配列(ndarray)を一貫して扱える
NumPyの中心となるデータ構造が、多次元配列のndarrayです。1次元(ベクトル)から2次元(行列)、さらに3次元以上のテンソルまで、同じ考え方・同じAPIで扱えるため、データの形状が複雑になっても設計がブレにくいのが特徴です。
ndarrayは、数値計算に適した「連続したメモリ上のデータ」を持ち、配列としての次元や形状を明確に管理できます。これにより、例えば画像(高さ×幅×色)や時系列データ(時間×特徴量)などの多次元データも、統一的な操作で処理できます。
import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
print(a.ndim) # 2(次元数)
print(a.shape) # (2, 3)(形状)また、ndarrayは「配列としての性質(形状・次元)」と「数値計算としての性質(型など)」を一体で管理できるため、python numpy を使うほど“データをどう持つか”が明確になり、後工程の計算も安定します。
ブロードキャストで異なる形状同士の計算を簡潔に書ける
NumPyには、形状(shape)が異なる配列同士でも、一定のルールに従って自動的に形状を合わせて計算できる「ブロードキャスト」という仕組みがあります。これにより、手作業で配列を複製したり、ループで調整したりする必要が減り、コードがシンプルになります。
代表例として、2次元配列(行列)の各行に対して、1次元配列(ベクトル)を加算するケースがあります。ブロードキャストにより、列数が一致していれば、各行に同じベクトルを足す処理を1行で書けます。
import numpy as np
A = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([10, 20, 30])
# (2,3) と (3,) の演算が成立(bが各行に自動的に適用される)
C = A + b
print(C)
# [[11 22 33]
# [14 25 36]]ブロードキャストは便利な一方、意図しない形状で計算が進んでしまうと結果の解釈が難しくなることがあります。python numpy で配列演算を行う際は、「どの次元が揃っていて、どこが自動拡張されるのか」を意識すると、ミスを防ぎつつ強力に活用できます。
利用前の準備(インストールと読み込み)

python numpyを使い始めるには、まず「インストール」と「読み込み(インポート)」の2点を押さえる必要があります。ここでつまずくと以降のコードが一切動かないため、実行環境(ローカル/仮想環境/クラウド)に合わせて確実に準備しましょう。
NumPyのインストール手順
NumPyはPythonの外部ライブラリなので、標準搭載されていない環境では事前にインストールします。一般的にはpipまたはcondaで導入しますが、どちらを使うかは環境によって決めるのが安全です。
1) pipでインストール(多くの環境で共通)
まず、Python自体が使える状態であることを確認した上で、次のコマンドを実行します。
python -m pip install numpy環境によってはpythonがPython 2を指すことがあるため、Python 3を確実に使うには以下も有効です。
python3 -m pip install numpy2) 仮想環境(venv)を使う場合
プロジェクトごとに依存関係を分離したい場合は、仮想環境を作ってからNumPyを入れるのが定石です。仮想環境を有効化した状態で、同様にpipインストールします。
# 仮想環境の作成(例)
python -m venv .venv
# 有効化(OSによりコマンドが異なります)
# 有効化後に実行
python -m pip install numpy仮想環境を使うことで、別プロジェクトのパッケージと衝突しにくくなり、再現性が高まります。
3) condaでインストール(Anaconda/Miniconda環境向け)
AnacondaやMiniconda環境では、conda管理下で入れると依存関係が解決しやすいケースがあります。
conda install numpy4) インストール確認(バージョンチェック)
インストールできたかどうかは、Python上でNumPyのバージョンを表示して確認するのが簡単です。
python -c "import numpy as np; print(np.__version__)"ここでエラーが出なければ、python numpyを利用する準備が整っています。もしModuleNotFoundError: No module named 'numpy'が出る場合は、インストール先のPythonと実行しているPythonが一致していない可能性が高いので、python -m pip形式で入れ直すと解決しやすいです。
NumPyのインポート方法
NumPyを使う際は、Pythonコードの先頭付近で「インポート(読み込み)」します。最も一般的な書き方は、慣習としてエイリアス(別名)npを付ける方法です。
基本形(推奨)
import numpy as np以降、NumPyの機能はnpを通して呼び出します。例えば、バージョン表示は次の通りです。
import numpy as np
print(np.__version__)別名を付けないインポート
エイリアスを使わずに書くこともできますが、コード量が増えるほど冗長になりがちです。
import numpy
print(numpy.__version__)よくある注意点(インポート時のエラー)
import numpy as npで失敗する場合は、インストールが完了していないか、実行環境が違う可能性があります(例:別の仮想環境・別のPythonを実行している)。- ファイル名を
numpy.pyにしてしまうと、ローカルファイルが優先されて正しいNumPyを読み込めずエラーになることがあります。スクリプト名はnumpy.pyやnumpyフォルダ名を避けるのが安全です。
インストールとインポートができれば、python numpyを使った数値計算のスタートラインに立てます。以降は、同じimport numpy as npを前提としてコードを書いていくのが一般的です。
ndarrayの基礎(作成・属性・データ型)

NumPyの中心となるデータ構造が、多次元配列であるndarrayです。python numpyで数値計算を行う際は、このndarrayを「どう作るか」「どんなデータ型で保持されるか」「何次元・どんな形状か」「どんな属性を持つか」を押さえることで、以降の操作(計算・加工・参照)が一気に理解しやすくなります。ここでは作成方法から基本属性までをまとめて整理します。
配列の作り方(arrayによる生成)
ndarrayを最も基本的に作る方法が、np.array()でPythonのリスト(入れ子も可)を配列に変換する手順です。まずは「1次元=リスト」「2次元=リストのリスト」という対応関係を理解すると直感的です。
import numpy as np
# 1次元配列
a = np.array([1, 2, 3])
# 2次元配列(行列のような形)
b = np.array([[1, 2, 3],
[4, 5, 6]])
print(a) # [1 2 3]
print(b) # [[1 2 3]
# [4 5 6]]np.array()は、渡した要素から「適切なデータ型(dtype)」を推定して配列を作ります。また、同じ行の長さが揃っていない入れ子リストなどは、意図通りの多次元配列にならない場合があるため、最初は「長方形(各行の要素数が同じ)」を意識して入力するのが安全です。
要素のデータ型(dtype)と型の考え方
NumPy配列では、原則として「配列内の要素はすべて同じ型(dtype)」として格納されます。これはPythonのリストと大きく異なる点で、python numpyが高速な数値計算に強い理由の一つです。
dtypeは自動推定されますが、状況によっては意図せず型が変わる(暗黙の型変換が起きる)ことがあります。例えば整数と浮動小数が混ざると、全体が浮動小数に寄るのが典型です。
import numpy as np
x = np.array([1, 2, 3])
y = np.array([1, 2.0, 3]) # floatが混ざる
print(x.dtype) # int64 など(環境依存)
print(y.dtype) # float64 など(環境依存)dtypeは明示的に指定することもできます。目的(メモリ節約、精度確保、他システムとのデータ互換など)に応じて型を固定したいときに有効です。
import numpy as np
z = np.array([1, 2, 3], dtype=np.float32)
print(z.dtype) # float32dtypeの理解で重要なのは次の観点です。
- 精度:
float32とfloat64では表現できる精度が異なる - メモリ:一般にビット数が大きいdtypeほどメモリ消費が増える
- 意図しない変換:混在データを渡すと自動的に「より表現範囲の広い型」に揃えられることがある
多次元配列(次元・形状)の基本
NumPyのndarrayは、1次元に限らず、2次元、3次元…といった多次元データをそのまま表現できます。ここで押さえるべき基本が「次元(dimension)」と「形状(shape)」です。
- 次元(ndim):配列が何次元か(軸の数)
- 形状(shape):各次元の要素数(例:2行3列なら
(2, 3))
例えば2次元配列は「行×列」のように捉えられ、3次元配列は「枚数×行×列(画像の集合など)」のように捉えられます。
import numpy as np
a1 = np.array([1, 2, 3]) # 1次元
a2 = np.array([[1, 2, 3], [4, 5, 6]]) # 2次元
a3 = np.array([[[1], [2]], [[3], [4]]]) # 3次元(例)
print(a1.ndim, a1.shape) # 1 (3,)
print(a2.ndim, a2.shape) # 2 (2, 3)
print(a3.ndim, a3.shape) # 3 (2, 2, 1)形状の読み方で混乱しやすいのが、1次元の(3,)のような「末尾カンマ」です。これはPythonのタプル表記で、(3)ではなく「要素が1つのタプル」であることを示しています。
配列が持つ主な属性(shapeなど)
ndarrayには、配列の状態を把握するための属性が用意されています。処理がうまくいかないときの原因特定や、意図したデータ構造になっているかの確認に欠かせません。特によく使うのが以下です。
| 属性 | 意味 | 例 |
|---|---|---|
ndim | 次元数(軸の数) | 2 |
shape | 形状(各次元の要素数) | (2, 3) |
size | 要素数(全要素の合計) | 6 |
dtype | 要素のデータ型 | int64 / float64 など |
実際に属性を確認する例です。
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr.ndim) # 2
print(arr.shape) # (2, 3)
print(arr.size) # 6
print(arr.dtype) # int64 など(環境依存)これらの属性を習慣的に確認できるようになると、python numpyで配列を扱う際の「想定と実データのズレ」を早期に発見でき、手戻りを大きく減らせます。
配列を生成する代表的な関数

python numpyでは、用途に応じて「配列(ndarray)を手早く作る」ための関数が用意されています。ここでは、連番・等間隔・初期化・乱数という実務でも頻出の4パターンに絞って、代表的な生成関数を整理します。どれも前処理やシミュレーション、テストデータ作成で役立つため、使い分けの基準を押さえておくと効率が上がります。
連番を作る(arange)
np.arangeは、一定の刻み幅(ステップ)で連続した値を持つ配列を生成する関数です。for文で1つずつ追加するのではなく、ベクトルとして一括で作れる点がNumPyらしい便利さです。
基本形は「開始値(start)から終了値(stop)未満まで、step刻みで作る」です。stopは含まれない(半開区間)ことが重要なポイントになります。
import numpy as np
# 0,1,2,3,4
a = np.arange(5)
# 2,4,6,8
b = np.arange(2, 10, 2)
# 小数ステップも可能(ただし誤差に注意)
c = np.arange(0, 1.0, 0.1)注意: 小数のstepを使うと、浮動小数点の丸め誤差により「期待した個数にならない」「末端がズレる」ことがあります。小数で“区間を等分したい”目的なら、次のlinspaceを使うのが安全です。
等間隔の値を作る(linspace)
np.linspaceは、指定した区間を「個数ベース」で等間隔に分割した値を生成します。arangeが「刻み幅(step)指定」なのに対し、linspaceは「点の数(num)指定」なのが使い分けの核心です。
import numpy as np
# 0.0〜1.0を5点に等分(両端を含むのがデフォルト)
x = np.linspace(0, 1, 5)
# array([0. , 0.25, 0.5 , 0.75, 1. ])
# endpoint=Falseで終端を含めない
y = np.linspace(0, 1, 5, endpoint=False)
# array([0. , 0.2, 0.4, 0.6, 0.8])例えば、グラフ用の横軸データやシミュレーションの時間軸など、「0〜TをN分割したい」といった要件では、python numpyのlinspaceが意図通りの配列を作りやすいです。
0/1で初期化する(zeros / ones)
np.zerosとnp.onesは、指定した形状(shape)の配列を、それぞれ0または1で埋めて生成します。処理前の“入れ物”や、初期値が決まっている配列を用意する場面で頻出です。
import numpy as np
# 1次元(要素数5)のゼロ配列
z1 = np.zeros(5)
# 2次元(3行2列)の1配列
o2 = np.ones((3, 2))
# dtypeでデータ型を指定(例:整数)
z_int = np.zeros((2, 3), dtype=int)ポイントは以下です。
- shapeはタプルで渡す(2次元以上は
(行, 列, ...)) - dtype指定で用途に合う型を作る(カウンタ用途ならintなど)
0/1の初期化ができると、あとから計算結果を代入したり、マスク(0/1で条件を表す)を作ったりと、NumPy配列を扱う土台が整います。
乱数配列を作る(random)
乱数で配列を作るには、NumPyの乱数生成機能を使います。近年の推奨はnp.random.default_rng()で生成器(Generator)を作り、そこから乱数を作る方法です。これにより、再現性(seed固定)やAPIの一貫性を保ちやすくなります。
import numpy as np
rng = np.random.default_rng(42)
# 0〜1の一様乱数(3行4列)
u = rng.random((3, 4))
# 整数乱数(0〜9)
r_int = rng.integers(0, 10, size=5)
# 平均0・標準偏差1の正規乱数
n = rng.normal(0, 1, size=(2, 3))乱数配列は、テストデータ生成、モンテカルロ法、機械学習の初期値などで利用されます。再現性が必要な場合はseedを固定し、チーム開発や検証で「同じ結果を再現できる」状態を作るのが重要です。
配列の要素を取り出す・切り出す

python numpy(NumPy)を使いこなすうえで欠かせないのが、「配列(ndarray)から必要な要素だけを参照・抽出する」操作です。データ分析や前処理では、特定の行や列だけを見たい、条件に合うデータだけを取り出したい、といった場面が頻繁にあります。このセクションでは、インデックス指定・スライス・整数配列インデックス・条件(真理値配列)という代表的な4つの方法を、コード例と一緒に整理します。
インデックス指定で要素を参照する
インデックス指定は「特定の位置の要素を1つ(または少数)取り出す」最も基本的な方法です。NumPy配列は0始まりで、1次元配列なら a[0] のようにアクセスします。負のインデックス(末尾から数える)も使えます。
import numpy as np
a = np.array([10, 20, 30, 40])
a[0] # 10
a[2] # 30
a[-1] # 40(末尾)
多次元(例:2次元)では、行・列をカンマで区切って指定します。arr[row, col] の形で書くのがNumPyの基本です。
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6]])
arr[0, 1] # 2(0行目の1列目)
arr[1, 2] # 6(1行目の2列目)
また、行(または列)を丸ごと参照したい場合は、片方を省略して取得できます。
arr[0] # array([1, 2, 3])(0行目)
arr[:, 1] # array([2, 5])(全行の1列目)
スライスで部分配列を取得する
スライスは「連続した範囲」を切り出す方法で、start:stop:step 形式で指定します。stop は含まれない点が重要です(Python標準のリストと同じ挙動)。
import numpy as np
a = np.array([0, 1, 2, 3, 4, 5])
a[1:4] # array([1, 2, 3])
a[:3] # array([0, 1, 2])
a[3:] # array([3, 4, 5])
a[::2] # array([0, 2, 4])(2つ飛ばし)
a[::-1] # array([5, 4, 3, 2, 1, 0])(逆順)
2次元以上でも、各次元ごとにスライスを指定できます。例えば「1〜3行目、0〜2列目」のように、行と列を同時に切り出せます。
import numpy as np
arr = np.arange(1, 13).reshape(3, 4)
# [[ 1, 2, 3, 4],
# [ 5, 6, 7, 8],
# [ 9, 10, 11, 12]]
arr[0:2, 1:3]
# array([[2, 3],
# [6, 7]])
なお、python numpyではスライスで得られる配列は「元データのビュー(参照)」になる場合があります。切り出した配列を変更すると元の配列にも影響する可能性があるため、独立した配列として扱いたいときは .copy() を使います。
sub = arr[:, :2] # ビューになる可能性
sub_copy = arr[:, :2].copy() # 明示的にコピー
整数配列インデックスで選択する
整数配列インデックス(ファンシーインデックス)は、「飛び飛びの位置」や「任意の順序」で要素を選びたいときに便利です。スライスが“連続範囲”なのに対し、こちらは“指定した番号の集合”を取り出せます。
1次元配列では、インデックスのリストやNumPy配列を渡します。
import numpy as np
a = np.array([10, 20, 30, 40, 50])
a[[0, 2, 4]] # array([10, 30, 50])
a[np.array([3, 1])] # array([40, 20])
2次元配列でも、行番号・列番号を指定して要素を抜き出せます。ここでのポイントは、arr[[行...], [列...]] のように「ペアで指定すると対応する要素が選ばれる」ことです。
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr[[0, 2], [1, 0]] # array([2, 7])((0,1) と (2,0) を取得)
「特定の行だけをまとめて取りたい」場合は、行の整数配列インデックスと列のスライスを組み合わせると分かりやすいです。
arr[[0, 2], :] # 0行目と2行目を取得
整数配列インデックスで得られる結果はコピーになるのが一般的で、スライス(ビューになりやすい)とは性質が異なります。用途としては「サンプリング」「並べ替え」「任意行抽出」などで活躍します。
条件(真理値配列)で抽出する(where等)
条件抽出(ブールインデックス)は、python numpyでデータを絞り込む際の定番です。配列に対して比較演算(>, == など)を行うと、同じ形状の真理値配列(True/False)が得られ、そのTrueの位置だけを抽出できます。
import numpy as np
a = np.array([3, 7, 1, 9, 5])
mask = a >= 5
mask # array([False, True, False, True, True])
a[mask] # array([7, 9, 5])
a[a >= 5] # 直接書いてもOK
複数条件を組み合わせるときは、Pythonの and/or ではなく、NumPyの要素ごとの演算である &(AND)や |(OR)を使い、各条件を括弧で囲みます。
import numpy as np
a = np.array([3, 7, 1, 9, 5])
a[(a >= 5) & (a <= 8)] # array([7, 5])
a[(a == 3) | (a == 9)] # array([3, 9])
np.where は「条件に合う要素の位置(インデックス)を得る」「条件に応じて値を振り分けた新しい配列を作る」といった用途で使われます。抽出だけでなく、後続処理につなげやすいのが特徴です。
import numpy as np
a = np.array([3, 7, 1, 9, 5])
# 条件に合う要素のインデックスを得る
idx = np.where(a >= 5)
idx # (array([1, 3, 4]),)
a[idx] # array([7, 9, 5])
# 条件に応じて値を置き換える(5以上は1、未満は0)
np.where(a >= 5, 1, 0) # array([0, 1, 0, 1, 1])
2次元配列でも同様に条件を適用できます。例えば「行列全体から条件を満たす要素だけを抽出」すると、結果は1次元にフラット化された形で返るのが一般的です。
import numpy as np
arr = np.array([[1, 8, 3],
[4, 5, 9]])
arr[arr >= 5] # array([8, 5, 9])
条件抽出は欠損値や外れ値の除外、しきい値処理などで特に重要です。インデックス指定・スライスと並び、NumPy配列から必要なデータだけを取り出す基本手段として押さえておくと、後続の処理が格段に書きやすくなります。
配列の形を変える・結合する
python numpyで配列(ndarray)を扱うとき、計算そのものと同じくらい重要なのが「形(shape)」です。形状が合わないと演算や代入ができなかったり、意図しない方向に連結されてしまったりします。この章では、shapeの確認から、reshapeによる形状変更、appendでの要素追加、concatenateでの配列結合までをまとめて押さえます。
形状確認と次元の捉え方(shape)
NumPy配列の形状は shape 属性で確認できます。shape は各次元の要素数をタプルで返し、「何行×何列」「何枚×何行×何列」といったサイズ感を把握する基礎になります。
import numpy as np
a1 = np.array([1, 2, 3])
a2 = np.array([[1, 2, 3],
[4, 5, 6]])
print(a1.shape) # (3,)
print(a2.shape) # (2, 3)次元の捉え方のポイントは以下です。
(3,)は1次元配列(ベクトル)で、行・列の概念が固定されません(2, 3)は2次元配列(行列)で、「2行3列」を意味します(n, 1)は列ベクトル、(1, n)は行ベクトルとして扱いやすくなります
また、全要素数を確認したいときは size、次元数は ndim が便利です。shapeと合わせて見るとミスが減ります。
b = np.array([[[1], [2]], [[3], [4]]]) # shape (2, 2, 1)
print(b.shape) # (2, 2, 1)
print(b.ndim) # 3
print(b.size) # 4形状を変更する(reshape)
reshape は、配列の要素数を保ったまま形状だけを変更します。python numpyではデータ前処理や、モデル入力の整形などで頻出です。
import numpy as np
x = np.arange(6) # [0 1 2 3 4 5]
y = x.reshape(2, 3) # 2行3列に変更
print(x.shape) # (6,)
print(y.shape) # (2, 3)
print(y) # [[0 1 2]
# [3 4 5]]reshapeの重要なルールは「変更後のshapeの積(要素数)が元と一致すること」です。一致しない場合はエラーになります。
x = np.arange(6)
# x.reshape(4, 2) # 要素数が合わないため ValueError になる要素数計算が面倒なときは、1つの次元を -1 にするとNumPyが自動推定します(推定できるのは1か所だけ)。
x = np.arange(12)
a = x.reshape(3, -1) # (3, 4) に自動決定
b = x.reshape(-1, 3) # (4, 3) に自動決定
print(a.shape) # (3, 4)
print(b.shape) # (4, 3)さらに「1次元に戻したい」場合は reshape(-1) が定番です。
m = np.array([[1, 2, 3], [4, 5, 6]])
flat = m.reshape(-1)
print(flat) # [1 2 3 4 5 6]
print(flat.shape) # (6,)なお、reshapeは状況によりビュー(同じデータを別形状で参照)になることがあります。形状変更後の配列を独立させたい意図がある場合は copy() を明示するのが安全です。
要素を末尾に追加する(append)
np.append は、配列の末尾に要素(または配列)を追加して新しい配列を返します。ここで重要なのは、NumPy配列は基本的にサイズ固定のため、appendは「破壊的に増やす」のではなく、新しい配列を作る点です。大量データで繰り返すと非効率になりやすいので、使いどころを理解しておきましょう。
まずは1次元の例です。
import numpy as np
a = np.array([1, 2, 3])
b = np.append(a, 4)
print(a) # [1 2 3]
print(b) # [1 2 3 4]複数要素の追加もできます。
a = np.array([1, 2, 3])
b = np.append(a, [4, 5, 6])
print(b) # [1 2 3 4 5 6]2次元以上で注意したいのが axis の扱いです。axis を指定しない(デフォルト)場合、いったん平坦化(flatten)してから末尾に追加されます。
m = np.array([[1, 2],
[3, 4]])
print(np.append(m, [5, 6]))
# axis未指定: [1 2 3 4 5 6] (1次元になる)行や列として追加したい場合は、axis を指定し、形状が一致するように追加する配列を整えます。
m = np.array([[1, 2],
[3, 4]])
# 行(axis=0)を追加:追加する側は(1,2)の形にする
m2 = np.append(m, [[5, 6]], axis=0)
print(m2)
# [[1 2]
# [3 4]
# [5 6]]
# 列(axis=1)を追加:追加する側は(2,1)の形にする
m3 = np.append(m, [[9], [10]], axis=1)
print(m3)
# [[ 1 2 9]
# [ 3 4 10]]axis指定時に形状が合わないとエラーになるため、追加対象のshapeを先に確認するのがコツです。
配列を連結する(concatenate)
np.concatenate は、複数の配列を指定した軸方向に連結する基本関数です。python numpyでデータを「縦に積む」「横に並べる」といった操作をする際の土台になります。
まず1次元の連結はシンプルです。
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5])
c = np.concatenate([a, b])
print(c) # [1 2 3 4 5]2次元配列では、axis によって連結方向が変わります。
axis=0:行方向(縦方向)に連結(行数が増える)axis=1:列方向(横方向)に連結(列数が増える)
x = np.array([[1, 2],
[3, 4]])
y = np.array([[5, 6],
[7, 8]])
v = np.concatenate([x, y], axis=0)
h = np.concatenate([x, y], axis=1)
print(v)
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
print(h)
# [[1 2 5 6]
# [3 4 7 8]]連結で最も多い失敗は「連結しない軸のサイズが揃っていない」ケースです。たとえば axis=0 で連結するなら列数(axis=1側)が一致している必要があります。
x = np.array([[1, 2],
[3, 4]])
z = np.array([[9, 10, 11]])
# np.concatenate([x, z], axis=0)
# 列数が一致しないため ValueError になる複数配列を一度に連結できるのも特徴です。データをまとめて結合したい場合に役立ちます。
a = np.array([1, 2])
b = np.array([3, 4])
c = np.array([5, 6])
d = np.concatenate([a, b, c])
print(d) # [1 2 3 4 5 6]最後に、連結前は必ず各配列の shape を確認し、「どのaxisを伸ばすのか」を先に決めると、numpyの形状エラーを最短で回避できます。
NumPyの演算(要素ごと・行列・ブロードキャスト)

python numpy(NumPy)を使う最大のメリットの一つが、配列(ndarray)に対する演算を「要素ごとに」「高速に」書ける点です。さらに、配列の形状が違っていてもブロードキャストによって自然に計算できたり、行列演算を明示的に書き分けられたりします。この章では、NumPy演算の基本パターンをまとめて押さえます。
スカラーと配列の四則演算(ベクトル化)
NumPyでは、配列に対してスカラー(単一の数)を足す・引く・掛ける・割るといった四則演算が、そのまま直感的に書けます。各要素に同じ演算が適用されるため、Pythonのfor文で回すよりも簡潔で高速になりやすく、これを「ベクトル化(vectorization)」と呼びます。
import numpy as np
a = np.array([1, 2, 3])
print(a + 10) # [11 12 13]
print(a - 1) # [0 1 2]
print(a * 2) # [2 4 6]
print(a / 2) # [0.5 1. 1.5]四則演算は、データの平行移動(+)、スケーリング(*)、正規化の前処理(/)など、機械学習・データ分析の下準備でも頻出です。スカラー演算が「配列の各要素に一括で作用する」点を理解すると、NumPyらしい書き方が一気に楽になります。
配列同士の要素ごとの演算
同じ形状(shape)の配列同士なら、四則演算は原則として「要素ごと(element-wise)」に行われます。例えば2つのベクトルを足せば対応する位置の要素同士が足され、掛け算でも同様に対応要素同士が掛け合わされます。
import numpy as np
x = np.array([1, 2, 3])
y = np.array([10, 20, 30])
print(x + y) # [11 22 33]
print(x - y) # [ -9 -18 -27]
print(x * y) # [10 40 90]
print(x / y) # [0.1 0.1 0.1]注意点として、「配列同士の * は行列積ではない」ことが重要です。NumPyの * はあくまで要素ごとの積であり、行列積をしたい場合は @(または np.matmul)を使います。ここを混同すると、意図しない計算結果になりがちです。
import numpy as np
A = np.array([[1, 2],
[3, 4]])
B = np.array([[10, 20],
[30, 40]])
print(A * B) # 要素ごとの積
# [[ 10 40]
# [ 90 160]]形状が違う配列の演算(ブロードキャストの実践)
NumPyの強力な機能が「ブロードキャスト(broadcasting)」です。これは、形状が異なる配列同士でも、一定のルールに従ってサイズが自動的に揃えられ、要素ごとの演算ができる仕組みです。うまく使うと、繰り返し処理や手作業のreshapeを減らし、python numpyのコードを短く保てます。
代表例として、ベクトル(1次元)を行列(2次元)の各行に足すケースがあります。
import numpy as np
M = np.array([[1, 2, 3],
[4, 5, 6]]) # shape: (2, 3)
v = np.array([10, 20, 30]) # shape: (3,)
print(M + v)
# [[11 22 33]
# [14 25 36]]このとき v は「(2, 3) にコピーされた」と考えると直感的ですが、実際には必要に応じて自動拡張されるイメージです(明示的な繰り返しを書かずに済むのが利点です)。
もう一つの典型は、列ベクトルを使って各行(または各列)に別々の値を足し引きするパターンです。ここでは reshape を使って形状を合わせ、ブロードキャストが発生しやすい形にします。
import numpy as np
M = np.array([[1, 2, 3],
[4, 5, 6]]) # (2, 3)
col = np.array([100, 200]).reshape(2, 1) # (2, 1)
print(M + col)
# [[101 102 103]
# [204 205 206]]ブロードキャストの実務的なポイントは次の通りです。
- 「どの軸に沿って広げたいか」を意識し、必要なら
reshapeで (n, 1) や (1, n) を作る - 意図しないブロードキャストで計算が通ってしまうとバグに気づきにくいので、演算前後でshapeを確認する習慣を持つ
ユニバーサル関数(ufunc)の使いどころ
NumPyには、配列全体に対して高速に作用する「ユニバーサル関数(ufunc)」が用意されています。四則演算と同じく要素ごとに適用され、内部実装が最適化されているため、python numpyで数値計算を行う際の基本部品になります。
代表的なufuncには、指数・対数・三角関数・平方根・絶対値などがあります。
import numpy as np
a = np.array([1, 4, 9])
print(np.sqrt(a)) # [1. 2. 3.]
print(np.abs([-1, 2, -3])) # [1 2 3]比較(大小)や丸めもufuncとして扱えるため、条件判定や前処理でも頻出です。
import numpy as np
x = np.array([0.2, 1.7, 2.5])
print(np.floor(x)) # [0. 1. 2.]
print(np.ceil(x)) # [1. 2. 3.]
print(np.round(x)) # [0. 2. 2.]
print(x > 1.0) # [False True True]ufuncの使いどころは、「for文で1つずつ処理したくなる操作」を配列のまま適用したい場面です。例えば、特徴量のスケーリング、値のクリップ、外れ値対策、非線形変換(log/exp)などは、ufuncでまとめて書くと可読性も性能も両立しやすくなります。
集計・並べ替え・代表的な基本関数
python numpyでは、配列(ndarray)に対して「集計」と「並べ替え」を簡潔に実行できます。データの傾向を素早く把握したり、条件に合う順番へ整形したりする際に、sumやmean、sortといった基本関数は頻出です。ここでは代表的な集計関数と並べ替えの使い方を、軸(axis)の考え方も含めて整理します。
合計・平均・最大・最小などの集計(sum/mean/max/min)
NumPyの集計は、配列全体に対する計算だけでなく、行方向・列方向など「どの方向に集計するか」をaxisで指定できるのが特徴です。2次元配列を例にすると、axis=0は「列方向(縦)」、axis=1は「行方向(横)」の集計になります。
import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
# 配列全体の集計
a.sum() # 21
a.mean() # 3.5
a.max() # 6
a.min() # 1
# axisで方向を指定した集計
a.sum(axis=0) # array([5, 7, 9]) 列ごとの合計
a.sum(axis=1) # array([ 6, 15]) 行ごとの合計
a.mean(axis=0) # 列ごとの平均
a.max(axis=1) # 行ごとの最大
実務での使いどころとしては、次のようなイメージが近いです。
sum:売上の合計、件数の合計、スコアの総和などmean:平均単価、平均値の傾向把握、センサー値の平滑化の第一歩max/min:ピーク検知、異常値候補の確認、レンジ(範囲)の把握
また、欠損値(NaN)が混ざる可能性がある配列では、通常のmean等だと結果がNaNになりやすい点に注意が必要です。NaNを無視して集計したい場合は、np.nanmean、np.nansum、np.nanmax、np.nanminを使うと集計が止まらずに済みます。
b = np.array([1.0, np.nan, 3.0])
np.mean(b) # nan
np.nanmean(b) # 2.0(NaNを除外)
さらに、集計値だけでなく「最大値・最小値がどこにあるか(インデックス)」が必要な場合は、argmaxやargminが役立ちます。集計結果を根拠に要素を特定する流れを作れるため、python numpyでの探索処理の基本パターンになります。
c = np.array([10, 5, 30, 20])
c.argmax() # 2(最大値30の位置)
c.argmin() # 1(最小値5の位置)
並べ替え(sort)
データを昇順・降順に整列することで、最小〜最大の傾向を見たり、上位N件を取り出す前処理を行ったりできます。NumPyの並べ替えは、大きく「配列を並べ替えた結果を返す」方法と「配列自体を並べ替える」方法に分かれます。
まず、元の配列を保持したまま並べ替え結果がほしい場合はnp.sortを使います。
import numpy as np
x = np.array([3, 1, 4, 1, 5])
np.sort(x) # array([1, 1, 3, 4, 5])
# x自体は変わらない
一方、配列をその場で並べ替えたい場合は、ndarrayのメソッドであるx.sort()を使います。メモリ効率を重視したいケースで有効ですが、元データが上書きされる点には注意が必要です。
x = np.array([3, 1, 4, 1, 5])
x.sort()
# x は array([1, 1, 3, 4, 5]) に変わる
2次元以上の配列では、集計と同様にaxisで「どの方向に並べ替えるか」を指定できます。指定しない場合は最後の軸(2次元なら各行)が対象になります。
m = np.array([[3, 1, 2],
[9, 7, 8]])
np.sort(m) # 各行を昇順に並べ替え(axis=-1相当)
np.sort(m, axis=0) # 各列を昇順に並べ替え
降順にしたいときは、np.sort自体に降順オプションはないため、並べ替え後に反転(スライス)するのがシンプルです。
x = np.array([3, 1, 4, 1, 5])
np.sort(x)[::-1] # array([5, 4, 3, 1, 1])
また、「並べ替え後の値」ではなく「並べ替えの順番(インデックス)」がほしい場合はargsortが定番です。元配列の参照順を作れるので、別配列を同じ順序で並べ替えるといった処理にもつながります。
x = np.array([30, 10, 20])
idx = np.argsort(x) # array([1, 2, 0])
x[idx] # array([10, 20, 30])
このようにpython numpyのsum/mean/max/minとsortは、配列の全体像を掴み、扱いやすい順序に整えるための基本セットです。まずは「配列全体」→「axis指定」→「NaN対応」→「インデックス取得」の順に押さえると、応用へ自然につながります。
線形代数(機械学習で頻出)

機械学習の実装では、特徴量ベクトルや重み、行列(データ行列)を使った計算が中心になります。python numpyはこれらの線形代数計算を高速かつ簡潔に書けるため、内積・行列積から基本的な行列演算までを押さえると、モデル計算の理解と実装が一気に進みます。
内積・行列積(dot)
NumPyにおけるdotは「内積」や「行列積」を行う代表的な関数です。機械学習で頻出の計算(例:重み付き和、線形変換)をそのまま表現できるのが強みです。
内積(ベクトル同士)は、2つのベクトルの対応要素を掛け合わせて足し上げた値です。例えば、特徴量ベクトルxと重みwの内積は、線形モデルの出力(スコア)としてよく登場します。
import numpy as np
x = np.array([1.0, 2.0, 3.0])
w = np.array([0.1, 0.2, 0.3])
# 内積(スカラーが返る)
y = np.dot(x, w)
print(y) # 1.4
行列積(2次元配列同士)では、左の行列の「行」と右の行列の「列」の内積を要素として計算します。データ行列X(サンプル×特徴量)に重み行列W(特徴量×出力)を掛ける、といった形はニューラルネットワークでも基本です。
import numpy as np
X = np.array([[1, 2, 3],
[4, 5, 6]]) # (2, 3)
W = np.array([[1, 0],
[0, 1],
[1, 1]]) # (3, 2)
Z = np.dot(X, W) # (2, 2)
print(Z)
# [[ 4 5]
# [10 11]]
なお、python numpyでは行列積はnp.dot以外に@演算子でも書けます(意味は行列積)。読みやすさの面でX @ Wが好まれる場面もあります。
Z = X @ W
注意:dotは「配列の次元」によって挙動が変わります。1次元同士なら内積、2次元同士なら行列積、というように意味が切り替わるため、形状(shape)を意識して使うことが大切です。
線形代数系の計算(行列演算の基本)
線形代数の基本操作は、モデルの前処理や学習アルゴリズムの中核に現れます。ここではpython numpyで頻出の「転置」「逆行列」「連立一次方程式」「固有値」など、行列演算の基礎をまとめます。
転置(transpose)は、行と列を入れ替える操作で、式の整形や内積・行列積の形状合わせに使います。NumPyでは.Tで簡単に転置できます。
import numpy as np
A = np.array([[1, 2, 3],
[4, 5, 6]]) # (2, 3)
AT = A.T # (3, 2)
print(AT)
単位行列(identity)は、逆行列や検算で使う基本要素です。np.eye(n)で作れます。
I = np.eye(3)
print(I)
逆行列(inverse)は、理論上は重要ですが、実務では「逆行列を明示的に求める」よりも、数値安定性の高い解法を使うのが一般的です。NumPyではnp.linalg.invで逆行列を求められます。
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 3.0]])
A_inv = np.linalg.inv(A)
print(A_inv)
# 検算:A @ A_inv ≈ I
print(A @ A_inv)
注意:行列が特異(det=0)だと逆行列は存在せず、np.linalg.invはエラーになります。また、存在しても数値的に不安定な場合があります。
連立一次方程式を解く(solve)は、「逆行列を掛ける」代わりに使われる代表的手法です。A x = bの形をnp.linalg.solve(A, b)で解けます。
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 3.0]])
b = np.array([1.0, 2.0])
x = np.linalg.solve(A, b)
print(x)
# 検算:A @ x ≈ b
print(A @ x)
行列式(det)は、行列が「潰れていないか(可逆か)」の目安として使われます。np.linalg.detで計算できます。
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 3.0]])
d = np.linalg.det(A)
print(d)
固有値・固有ベクトル(eig)は、主成分分析(PCA)などの基礎で登場します。NumPyではnp.linalg.eigで計算できます(実対称行列ならnp.linalg.eighがよく使われます)。
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 3.0]])
vals, vecs = np.linalg.eig(A)
print(vals) # 固有値
print(vecs) # 列ベクトルが固有ベクトル
これらの線形代数計算をpython numpyで扱えるようになると、「数式で見た処理」をそのままコードに落とし込みやすくなり、機械学習の理解と実装速度が上がります。特にdot(または@)とnp.linalg周りは頻出なので、形状(shape)とセットで慣れていくのがポイントです。
データの保存と読み込み(再現性のための入出力)

python numpyで作った配列(ndarray)は、前処理・特徴量作成・実験結果などをそのまま保存しておくと、あとから同じ状態を正確に再現できます。特に機械学習やデータ分析では「同じ入力から同じ結果を得られること(再現性)」が重要になるため、NumPyの入出力(I/O)を押さえておくと作業が安定します。
保存形式は大きく分けて、NumPy専用のバイナリ形式(高速・安全)と、テキスト形式(人が読めるが遅くサイズが増えやすい)があります。用途に応じて使い分けましょう。
配列の保存と復元の基本
ここでは「ndarrayを保存し、同じ配列として読み戻す」ための基本を整理します。結論としては、単一配列ならsave/load、複数配列ならsavez/loadをまず使うのが安全です。
1) 単一配列を保存・復元する(.npy)
.npyはNumPyの標準的な配列保存形式です。dtypeやshapeなど配列のメタ情報も含めて保存されるため、読み込み後に元の配列を高い確度で復元できます。
import numpy as np
x = np.arange(10, dtype=np.int64)
# 保存(拡張子 .npy)
np.save("x.npy", x)
# 読み込み
x2 = np.load("x.npy")
print(x2.dtype, x2.shape)
基本的にはこれだけでOKです。保存先は相対パスでも絶対パスでも指定できます。
2) 複数配列をまとめて保存・復元する(.npz)
前処理後の特徴量配列や、学習用・検証用データなど、複数のndarrayを一緒に管理したい場合は.npzが便利です。名前付きで保存しておくと、読み込み時にキーで取り出せます。
import numpy as np
a = np.random.rand(3, 4)
b = np.array([1, 2, 3], dtype=np.int32)
# 名前付きで保存
np.savez("dataset.npz", features=a, labels=b)
# 読み込み(戻り値は NpzFile のような辞書的オブジェクト)
data = np.load("dataset.npz")
a2 = data["features"]
b2 = data["labels"]
print(a2.shape, b2.dtype)
読み込み後は、保存時に付けたキー(上例ならfeaturesやlabels)でアクセスします。
3) 圧縮して保存する(サイズ削減)
ファイルサイズを抑えたい場合はsavez_compressedを使う選択肢があります。ディスク容量や受け渡しを重視するケースで有効ですが、圧縮・解凍の分だけ処理時間が増える点には注意が必要です。
import numpy as np
x = np.random.rand(1000, 1000)
np.savez_compressed("big_array.npz", x=x)
data = np.load("big_array.npz")
x2 = data["x"]
4) テキスト形式(CSV等)で保存・読み込みする
他ツール(スプレッドシート、別言語)との連携や、人が直接中身を確認したい場合はテキスト形式が役立ちます。NumPyではsavetxtとloadtxtが基本です。ただし、テキストはバイナリより容量が増えやすく、浮動小数点の桁落ちなどで厳密な再現性が下がることがあります。
import numpy as np
m = np.array([[1.5, 2.0, 3.25],
[4.0, 5.125, 6.0]])
# CSVとして保存(区切り文字 delimiter を指定)
np.savetxt("matrix.csv", m, delimiter=",", fmt="%.6f")
# 読み込み
m2 = np.loadtxt("matrix.csv", delimiter=",")
print(m2)
5) 読み込み時の注意点(dtype・allow_pickle)
dtypeの保持:
.npy/.npzは基本的にdtypeを保持して復元できます。一方、loadtxtなどテキスト読み込みは型推定になりやすいため、意図したdtypeになっているか確認しましょう。セキュリティ:
np.loadにはallow_pickleという引数があります。通常の数値配列なら不要で、不明なファイルを読み込む際に安易に有効化しないのが安全です(オブジェクト配列等で必要になる場合のみ検討)。
6) 再現性を高める運用のコツ(ファイル設計)
python numpyで保存した配列を「あとで確実に使える状態」にするには、保存そのものだけでなく、ファイルの扱い方も重要です。
ファイル名に意味を持たせる:例)
features_v1.npzのようにバージョンや条件を含める。同時にメタ情報を残す:配列だけでなく、作成日時・前処理条件などを別途テキストで保存すると、後から追跡しやすくなります(配列そのものの入出力とは分けて管理するのが無難です)。
相対パス前提の保存:プロジェクト内の
data/配下などにまとめると、別環境への移行時も壊れにくくなります。
NumPyが機械学習・AIで使われる理由

機械学習やAIの処理は、本質的に「大量の数値を、繰り返し計算する」ことの連続です。データ前処理で特徴量を整え、学習でパラメータを更新し、推論で新しい入力に対して計算を行う——この一連の流れでは行列・ベクトル演算が中心になります。Pythonの中でも python numpy は、この数値計算を現実的な速度と開発効率で回すための定番基盤として、幅広いAI開発で採用されています。
大規模な数値計算を高速に回せるため
機械学習では、データ数(サンプル数)×特徴量数の規模が大きくなりやすく、計算の重さがそのまま学習時間に跳ね返ります。NumPyが重宝される最大の理由は、こうした大規模な数値計算を「Pythonの書きやすさのまま、速く」実行できる点にあります。
具体的には、NumPy配列(ndarray)に対する計算は、要素ごとの処理をPythonのfor文で回すのではなく、内部で最適化されたループにより一括で処理されます。その結果、学習で頻出する演算を高スループットで回しやすくなります。
- 行列・ベクトル演算が前提のワークロードに強い:線形回帰やロジスティック回帰、ニューラルネットワークの計算は、行列積・加算・活性化関数といった数値演算の積み重ねです。
- バッチ処理(まとめて計算)と相性が良い:学習ではデータをまとめて処理することが多く、NumPyの配列演算はこの形に自然にフィットします。
- メモリ上で連続的に扱えるデータ構造:大量データを配列として保持し、同じ形の演算を繰り返すAIの処理モデルに適しています。
つまり、python numpy を使うことで「試行錯誤の回転数」を上げやすくなります。学習時間が短いほど改善サイクル(特徴量の見直し、モデル変更、ハイパーパラメータ調整)を回しやすくなり、結果としてモデル品質にもつながります。
学習・推論で役立つ関数が豊富に揃っているため
AI開発では、モデル本体の計算だけでなく、前処理・評価・推論パイプラインといった周辺作業も含めて「数値を扱う工程」が多数あります。NumPyはこの周辺工程で必要になる関数群が充実しており、学習・推論の実装をシンプルに保てる点も採用理由です。
- 統計・集計の基本関数が揃う:平均、分散、標準偏差、最大最小などの計算は、データのスケーリングや分布確認、評価指標の下準備で頻繁に使われます。
- 配列操作が豊富:データを「整形する」作業(必要な列の抽出、条件での絞り込み、欠損の扱い、形状の変換など)は学習前に必須で、NumPyの配列操作がそのまま武器になります。
- 数学関数が推論処理に直結する:指数・対数・三角関数などの数学関数は、活性化関数やスコア変換、確率の計算などで活用されます。
これらが揃っていることで、学習時は「データを目的の形に整える→計算する→結果を評価する」、推論時は「入力を同じ前処理で整える→スコアを計算する→出力に整形する」という流れを、同じpython numpyの文脈で一貫して書きやすくなります。結果として、実装の見通しが良くなり、バグやロジックの取り違えも抑えやすくなるのが大きな利点です。
実践例:NumPyで押さえる統計計算と分析の入口

python numpyは「配列を高速に扱う」だけでなく、データ分析の入口となる統計計算も手早く実装できます。ここでは、まず基本的な統計量(平均・分散・標準偏差など)を計算する流れを押さえ、その延長として「重回帰(複数の説明変数で目的変数を予測する)」をNumPyだけで動かす最小例を紹介します。Pandasなどを使わずとも、配列としてデータを持てば分析の骨格を確認できるのがポイントです。
基本的な統計量を計算する手順
統計量の計算は、(1) データを配列にする、(2) 欠損や外れ値などを意識しながら集計する、(3) 必要なら軸(axis)を指定して「列ごと・行ごと」に計算する、という順で進めると迷いにくくなります。以下では、1次元データと2次元データ(複数列)を想定して、NumPyの典型的な使い方をまとめます。
import numpy as np
# 例:1次元データ(売上、点数など)
x = np.array([10, 12, 9, 15, 14], dtype=float)
# 基本統計量
mean = np.mean(x) # 平均
median = np.median(x) # 中央値
min_v = np.min(x) # 最小
max_v = np.max(x) # 最大
ptp_v = np.ptp(x) # 範囲(max-min)
var_pop = np.var(x) # 分散(母分散、ddof=0)
std_pop = np.std(x) # 標準偏差(母標準偏差、ddof=0)
var_samp = np.var(x, ddof=1) # 不偏分散(標本分散)
std_samp = np.std(x, ddof=1) # 標本標準偏差
# 合計・件数
total = np.sum(x)
n = x.size
(mean, median, min_v, max_v, ptp_v, var_pop, std_pop, var_samp, std_samp, total, n)
実務で頻出なのが「列ごとの統計量」です。たとえば、複数特徴量(身長・体重・年齢など)を列に持つ2次元配列を扱う場合、axisを指定して“どの方向に集計するか”を明確にします。
import numpy as np
# 例:2次元(行=サンプル、列=特徴量)
X = np.array([
[170, 65, 30],
[165, 55, 22],
[180, 75, 35],
[175, 68, 28],
], dtype=float)
# 列ごとの平均・標準偏差(axis=0:行方向に集約=各列の統計量)
col_mean = np.mean(X, axis=0)
col_std = np.std(X, axis=0, ddof=1)
# 行ごとの合計(axis=1:列方向に集約=各行の集計)
row_sum = np.sum(X, axis=1)
(col_mean, col_std, row_sum)
もう一歩だけ分析っぽくするなら、標準化(平均との差を標準偏差で割る)をNumPyで組めます。標準化は、特徴量のスケール差を均す前処理として重要ですが、ここでは「統計量を使って変換できる」ことを確認するのが狙いです。
import numpy as np
X = np.array([
[170, 65, 30],
[165, 55, 22],
[180, 75, 35],
[175, 68, 28],
], dtype=float)
mu = np.mean(X, axis=0)
sigma = np.std(X, axis=0, ddof=0)
# ゼロ除算回避(分散0の列があるケースに備える)
sigma_safe = np.where(sigma == 0, 1.0, sigma)
X_z = (X - mu) / sigma_safe
X_z
相関も「入口の分析」としてよく使います。NumPyでは相関係数行列をnp.corrcoefで計算できます(行・列の解釈に注意し、列を変数として扱うならrowvar=Falseが分かりやすいです)。
import numpy as np
X = np.array([
[170, 65, 30],
[165, 55, 22],
[180, 75, 35],
[175, 68, 28],
], dtype=float)
corr = np.corrcoef(X, rowvar=False) # 列=変数
corr
このように、python numpyだけでも「平均・ばらつき・標準化・相関」まで一通り触れます。次のステップとして、これらの統計量が“モデル化(回帰)”でどう使われるかを、重回帰の最小例で確かめます。
NumPyを使った重回帰の最小例
重回帰は「目的変数yを、複数の説明変数Xの線形結合で表す」手法です。NumPyでは、最小二乗法(誤差平方和が最小になる係数)をnp.linalg.lstsqで求めるのが最もシンプルです。ここでは、(1) データ行列Xを作る、(2) 切片(定数項)を追加する、(3) 最小二乗で係数を推定する、(4) 予測と誤差(残差)を確認する、という流れで最小例を示します。
import numpy as np
# 例:説明変数(2特徴量)と目的変数
# X: [広告費, 訪問数] のようなイメージ
X = np.array([
[1.0, 10.0],
[2.0, 12.0],
[3.0, 13.0],
[4.0, 15.0],
[5.0, 18.0],
], dtype=float)
# y: 売上など(ここでは例として適当な数値)
y = np.array([8.0, 9.5, 10.0, 12.0, 13.5], dtype=float)
# 切片(バイアス)を入れる:先頭列に1を追加
X_design = np.c_[np.ones(X.shape[0]), X] # shape: (n_samples, 1 + n_features)
# 最小二乗解を求める
# beta = [b0, b1, b2](b0が切片)
beta, residuals, rank, s = np.linalg.lstsq(X_design, y, rcond=None)
beta, residuals, rank
推定した係数betaを使えば、予測値は単に行列積で計算できます。NumPyの配列演算だけで、回帰の「予測→残差→当てはまりの確認」までつながります。
import numpy as np
# 上の続きとして想定
y_pred = X_design @ beta
resid = y - y_pred
# 代表的な誤差の見方(ここでは最小例としてMSEのみ)
mse = np.mean(resid ** 2)
y_pred, resid, mse
重回帰でつまずきやすいのが、配列形状の扱いです。特に、Xが2次元、yが1次元、切片追加後のX_designが「(サンプル数, 特徴量数+1)」になっているかを確認すると、行列積(@)のエラーを避けやすくなります。
X.shape:(n_samples, n_features) になっているかX_design.shape:(n_samples, n_features+1) になっているか(切片列を追加した分)y.shape:通常は(n_samples,)でOK(列ベクトルにしたいならy.reshape(-1, 1))
この最小例を動かせれば、「python numpyで統計量を計算する」だけでなく、「統計量の先にあるモデル化(回帰)」まで一続きで理解できます。まずは小さな配列で形状と計算結果を確認し、係数・予測・残差の関係を手で追える状態を作るのが効果的です。
学習を次に進めるためのロードマップ

Python NumPyの基本操作を一通り触ったあと、「次は何を学べば実務や研究に繋がるのか」で迷う方は少なくありません。ここでは、理解を一段深めるために押さえたい学習ポイントと、次に学ぶと効果的な周辺ライブラリを、ロードマップとして整理します。
理解を深めるための学習ポイント(つまずきやすい点)
NumPyは書き方自体はシンプルですが、結果の形(shape)が意図とズレたり、処理速度が出なかったりと、学習が進むほど「落とし穴」が増えます。以下のポイントを意識して復習すると、Python NumPyの理解が実務レベルに近づきます。
shape(形状)と次元の扱いを「図で説明できる」まで理解する
つまずきの多くはshape由来です。特に、1次元配列
(n,)と列ベクトル(n, 1)の違いは頻出です。演算前にarr.shapeを確認する癖をつけ、必要に応じてreshapeや次元追加(例:[:, None])を使って意図した形に揃える練習をしましょう。ブロードキャストを「ルール」で理解して、事故を防ぐ
NumPyのブロードキャストは強力ですが、意図しない拡張で「計算は通るのに結果が間違う」ことがあります。ポイントは、末尾次元から順に比較され、
同じかどちらかが1なら拡張される、というルールです。手計算で「どの次元が伸びたか」を説明できるようにしておくと、デバッグが速くなります。スライスとビュー(view)/コピー(copy)の違いを理解する
NumPy配列のスライスは、多くの場合「元配列のビュー」を返します。つまり、切り出した配列を変更すると元も変わることがあります。これがバグの原因になりがちです。安全側で進めたい場面では
.copy()を明示し、「参照を共有してよいのか?」を判断できるようにしましょう。dtype(データ型)と精度・メモリのトレードオフを意識する
Python NumPyでは、
float64が暗黙に選ばれやすい一方、用途によってはfloat32の方がメモリ効率がよく、計算も速い場合があります。また、整数型同士の割り算や型変換(キャスト)で精度が変わる点にも注意が必要です。arr.dtypeを確認し、必要ならastypeで型を揃える習慣を持つと、再現性と性能が安定します。「速い書き方」を判断できる:ループよりベクトル化、ただし万能ではない
NumPyはベクトル化で高速化しやすい反面、無理に複雑なベクトル化をすると可読性が落ちたり、一時配列が増えて遅くなったりします。まずは「Pythonのforを減らし、NumPyの演算に寄せる」を基本にしつつ、メモリ使用量や中間結果(配列のサイズ)にも目を向けて学習を進めるのが効果的です。
エラー文に慣れる:ValueErrorの読み方が上達の近道
典型例は
operands could not be broadcast togetherのような形状不一致です。エラーが出たら「今のshapeは何か」「どの演算でブロードキャストが破綻したか」を確認し、配列の形を揃える→再実行、の手順をルーチン化しましょう。結果として、NumPyを使った実装の修正が速くなります。
次に学ぶと効果的な周辺ライブラリ(Pandas/Matplotlib等)
NumPyの基礎が固まったら、目的に応じて周辺ライブラリへ進むと、学んだ内容が一気に「使えるスキル」になります。ここでは、NumPyを土台に学びやすく、相乗効果が高いライブラリを優先度順に紹介します。
Pandas(表形式データの前処理・集計)
実務データは「表(行・列)」で扱うことが多く、NumPy配列だけでは列名や欠損値などの扱いが煩雑になりがちです。PandasはDataFrameにより、読み込み→整形→集計の流れが強力になります。NumPyで学んだ「配列演算の考え方」は、Pandasの列演算や欠損処理にも直結します。
Matplotlib(可視化で理解と検証を加速)
NumPyで計算した結果は、プロットすると誤りに気づきやすくなります。たとえば、配列の形状ミスやスケーリングミスは数値の羅列だけでは見抜きにくいものです。Matplotlibで折れ線・散布図・ヒストグラムを描けるようになると、「計算が正しいか」を素早く検証でき、学習効率が上がります。
SciPy(最適化・統計・信号処理など“数値計算の実戦道具”)
SciPyはNumPyを基盤にしたライブラリ群で、より高度な数値計算(最適化、統計、線形代数の発展的機能など)を扱えます。「NumPyで配列を作ってSciPy関数に渡す」という流れが自然で、Python NumPyの理解がそのまま武器になります。
scikit-learn(機械学習の標準ライブラリ)
機械学習を次のステップにしたいなら、scikit-learnが王道です。入力データを「行=サンプル、列=特徴量」の2次元配列として扱う場面が多く、NumPyのshape設計・前処理・分割の感覚がそのまま効きます。まずはデータ準備の部分でNumPyの配列操作が活躍します。
Jupyter(試行錯誤の速度を上げる実行環境)
ライブラリそのものではありませんが、学習・検証の流れを加速する上で重要です。配列の中身やshapeを逐次確認しながら進められるため、NumPyで起きがちな「形状の取り違え」を早期に発見できます。学習時は特に、実験→確認→修正のサイクルを短くできる環境が効果的です。
この順に周辺ライブラリへ進むと、NumPyで学んだ配列操作と数値計算の基礎が、データ処理・可視化・解析へと自然に繋がります。目的(分析したいのか、可視化したいのか、機械学習に進みたいのか)に合わせて選ぶことで、python numpy学習の投資対効果が高まります。

