この記事ではNumPyの概要と重要性を押さえつつ、高速な数値計算・多次元配列・ブロードキャストなどの特徴、機械学習で使われる理由を解説します。インストール/インポート方法から、append・where・arange・mean・reshape・dot・random等の基本関数まで学べ、配列操作や行列計算に迷う悩みを解決できます。
目次
- 1 NumPy(np)とは何か:Python数値計算の標準ライブラリ
- 2 NumPyの主要な特徴(ndarray・高速化・ブロードキャスト)
- 3 導入手順:インストールとimportの基本
- 4 ndarray入門:配列の作成と基本プロパティ
- 5 配列の参照・抽出:インデックス/スライス/条件抽出
- 6 配列計算の基本:要素ごとの演算とユニバーサル関数
- 7 集計・統計:sum/max/min/meanなど頻出関数
- 8 形状操作と結合:reshape・append・concatenate
- 9 ソートと並べ替えの基礎
- 10 行列計算と線形代数:dot・行列積・関連演算
- 11 データの保存と読み込み:np.save/np.loadによる永続化
- 12 機械学習・深層学習でNumPyが使われる理由
- 13 NumPyを使った簡単な分析例:重回帰の流れを体験
- 14 次に学ぶと役立つ周辺ライブラリ
NumPy(np)とは何か:Python数値計算の標準ライブラリ

NumPyの概要とできること
Pythonで数値計算を行うとき、最初に名前が挙がる標準的なライブラリがNumPyです。多くの現場では import numpy as np のように読み込まれるため、「python np」という形で検索されることも多く、NumPy=npという略称が定着しています。
NumPyの中心にあるのは、多次元配列(ndarray)というデータ構造です。Pythonのリストでも数値の集合は扱えますが、NumPyの配列を使うことで「数値計算に最適化された形」でデータをまとめ、計算処理を効率よく実行できます。
NumPyでできることは幅広く、代表的には次のような用途で活躍します。
配列(ベクトル・行列)の作成と管理:数値データを1次元〜多次元で保持し、サイズや形状を保ったまま扱えます。
要素ごとの高速な計算:加算・減算・乗算・除算などの基本演算を配列に対してまとめて適用できます。
数学関数の適用:指数・対数・三角関数など、数値計算で頻出の関数を配列に一括で適用できます。
統計・集計の土台:合計、平均、分散など、分析の前処理で必要な集計をスムーズに行えます。
データサイエンス/機械学習の前提知識:後続の可視化・分析・学習ライブラリがNumPy配列を前提に設計されているケースが多いです。
このようにNumPyは、「Pythonで数値データを扱うための共通言語」のような位置づけです。コード例や解説でもnpという省略名が標準的に使われるため、python npで調べる際は「NumPyの使い方」を探しているケースがほとんどだと理解しておくとスムーズです。
NumPyを学ぶべき理由(高速な数値計算・周辺ライブラリとの親和性)
NumPyを学ぶ価値は大きく分けて2つあります。1つは高速な数値計算、もう1つは周辺ライブラリとの親和性です。python npを入り口にNumPyを押さえることで、Pythonによる分析・機械学習・科学技術計算の基礎体力がつきます。
高速な数値計算という点で、NumPyは「まとめて計算する」ことが得意です。Pythonのfor文で要素を1つずつ処理するよりも、配列に対して演算を一括で適用する書き方のほうが、処理時間を短縮しやすくなります。実務ではデータ量が増えるほど差が顕在化するため、数値処理を扱うならNumPyを前提に組み立てるのが定石です。
次に周辺ライブラリとの親和性です。Pythonにはデータ分析や機械学習のためのライブラリが多数ありますが、それらの多くが「入力・出力としてNumPy配列(またはそれに準じる形式)を扱える」よう設計されています。つまり、NumPy(np)の配列操作に慣れておくと、別のライブラリへ移ったときもデータの受け渡しや前処理で迷いにくくなります。
まとめると、NumPyは「速く計算するための道具」であると同時に、「Python数値計算エコシステムの中心にある共通基盤」です。python npで調べている段階で基礎を固めておくことが、後の学習コスト削減と実装スピード向上に直結します。
NumPyの主要な特徴(ndarray・高速化・ブロードキャスト)

Pythonで数値計算をする際、「for文で回すと遅い」「データが2次元・3次元になると扱いづらい」「形の違う配列同士の計算が面倒」といった壁にぶつかりがちです。NumPy(import時にnpという別名で呼ばれることが多い)は、これらをまとめて解決するための仕組みを備えています。このセクションでは、NumPyの核となる3要素であるndarray、高速化、ブロードキャストのポイントを押さえます。
高速に処理できる仕組みの概要
NumPyが高速なのは、Pythonのリストを要素ごとに処理するのではなく、配列全体をまとめて計算する設計になっているためです。とくにpython npで数値計算を始めると、同じ計算でも体感できるほど速度差が出ることがあります。
高速化の要点は次のとおりです。
- 連続したメモリ配置を前提にした配列:NumPy配列は(一般に)同じ型の数値がまとまって格納され、CPUが扱いやすい形になります。
- ベクトル化(vectorization):Pythonのループで1要素ずつ計算する代わりに、配列演算として一括で処理します。
- 内部処理が低レベル実装:配列演算は低レベル側で最適化されたルーチンにより実行され、Pythonのインタプリタ処理コストを避けやすいです。
ここで重要なのは、「NumPyの関数・演算で書ける形に寄せるほど速くなりやすい」という実務上のコツです。つまり、同じ処理でもforで回すより、npの配列演算として表現できるかが性能を左右します。
多次元配列(ndarray)でデータを扱える
NumPyの中心にあるデータ構造がndarray(N-dimensional array)です。1次元のベクトルから、2次元の行列、さらに3次元以上のテンソルまで、同じ概念で扱えるため、データの形が複雑になっても記述が破綻しにくいのが特徴です。
ndarrayが数値計算に向く理由を、使いどころとセットで整理します。
- 形状(shape)という概念で、行列・テンソルを自然に表せる:画像(高さ×幅×チャンネル)、時系列×特徴量、バッチ×系列長×埋め込み次元などを素直に表現できます。
- 同一データ型(dtype)を前提にしやすい:数値計算では「全要素がfloat」など型が揃っている方が計算効率と安定性が上がります。
- 要素単位の演算が標準:配列同士の足し算・掛け算などが「各要素に対して」自然に適用されます(後述のブロードキャストとも相性が良いです)。
実務では、表計算のような2次元だけでなく、複数の軸を持つデータが頻出します。python npを使う最大の旨味は、こうした多次元データを「同じルール」で統一的に処理できる点にあります。
ブロードキャストで異なる形状でも計算できる
NumPyの強力な機能の一つがブロードキャスト(broadcasting)です。これは、形状(shape)が完全に一致しない配列同士でも、一定のルールに従って自動的に次元を揃え、計算を成立させる仕組みです。スカラー(単一の数)と配列の演算が自然にできるのもブロードキャストのおかげです。
ブロードキャストの基本的な考え方は次の通りです。
- 不足している次元は「1」とみなして補われる:右側(末尾側)の次元を基準に揃えます。
- 各次元のサイズが一致するか、どちらかが1ならOK:サイズ1の軸は、必要に応じて繰り返されたように扱われます。
具体例として、配列の各列から平均を引く「中心化」のような処理は、ブロードキャストがあると簡潔に書けます。
# 例:2次元配列Xの各列から列平均を引くイメージ
# X: (行数, 列数)
# mean: (列数,) でも (1, 列数) のように扱われ、行方向に自動で広がる
X_centered = X - X.mean(axis=0)
このように、わざわざ平均を行数分コピーした配列を作らなくても、npが内部で整合する形に解釈して計算してくれます。
一方で、ブロードキャストは便利な反面、意図しない形状で計算が進むとバグの原因になります。とくに「(n,) と (n,1) の違い」のように見た目が似た形状でも結果が変わることがあるため、どの軸が揃って計算されるのかを意識して使うことが重要です。
導入手順:インストールとimportの基本

Pythonで数値計算を始めるとき、まず押さえておきたいのが「NumPyを入れて使える状態にする」ことです。特に検索でもよく見かける python np は、NumPyを np という短い別名で扱う定番の書き方を指します。このセクションでは、インストールと読み込み(import)の基本だけに絞って、最小でつまずかない手順を整理します。
NumPyのインストール方法
NumPyは外部ライブラリのため、標準状態のPythonには入っていないことがあります。一般的には pip を使ってインストールします。まずはターミナル(WindowsならPowerShellやコマンドプロンプト、macOS/LinuxならTerminal)で次を実行してください。
pip install numpy環境によっては pip が別のPythonに紐づいていて、意図した環境に入らないことがあります。その場合は、起動しているPythonに対して確実にインストールできる形として、次のように実行すると安全です。
python -m pip install numpy複数のPython(例:Python 2/3、あるいは複数バージョン)を使っている場合は、次のように python3 を明示するケースもあります。
python3 -m pip install numpyインストールできたか不安なときは、バージョン確認まで行うと確実です。
python -c "import numpy; print(numpy.__version__)"ここでエラーが出ずにバージョン文字列が表示されれば、NumPyの導入は完了です。なお、インストール時に権限エラーが出る場合は、環境の設定(管理者権限や仮想環境の利用状況など)が影響している可能性があります。まずは「実行しているPython」と「インストール先」が一致しているかを確認するのが近道です。
NumPyの読み込み(import numpy as np)
NumPyを使う際の基本形は、次の1行です。これが「python np」と呼ばれる定番スタイルの中心になります。
import numpy as npas np は別名(エイリアス)を付ける構文で、numpy を毎回フルで書かずに np で参照できるようにします。たとえば、NumPyの関数や機能は np 経由で呼び出すのが一般的です。
import numpy as np
print(np.__version__)このように書くメリットは次の通りです。
- コードが短く読みやすい(
numpyを繰り返し書かない) - 多くのサンプルコードと同じ表記になり、学習・検索時に迷いにくい(python np の形が標準)
- 名前の衝突を避けやすい(同名の変数・関数をうっかり作っても影響範囲を限定できる)
逆に、次のような書き方は可能ではあるものの、学習初期は混乱しやすいため一般的には推奨されません。
import numpy(呼び出しがnumpy.〜になり冗長になりがち)from numpy import *(名前が大量に展開され、何がNumPy由来か分かりにくい)
まずは import numpy as np を「NumPyを使う合図」として覚えるのが、最短で安定する導入手順です。
ndarray入門:配列の作成と基本プロパティ

NumPy(np)の中心にあるデータ構造が、多次元配列の「ndarray」です。ndarrayを使いこなす第一歩は、配列の作り方と、作った配列が「どんな形で・どんな型で」並んでいるか(プロパティ)を確認できるようになることです。ここでは、Pythonでの数値計算に欠かせない基本操作として、配列の生成と属性確認をまとめて押さえます。
arrayで配列を作る基本
もっとも基本的な作成方法は、Pythonのリスト(またはタプル)をnp.array()に渡してndarrayへ変換する方法です。1次元だけでなく、入れ子のリストにすれば2次元(行列)以上も作れます。
import numpy as np
# 1次元配列
a = np.array([1, 2, 3])
print(a) # [1 2 3]
# 2次元配列(行列)
b = np.array([[1, 2, 3],
[4, 5, 6]])
print(b)
# [[1 2 3]
# [4 5 6]]
np.array()は、入力データから適切なdtype(データ型)を推論します。小数が混ざれば浮動小数点型になるなど、統一できる型に自動変換される点は便利な一方、意図しない型になることもあるため、必要に応じてdtype指定も検討します(後述)。
arange・linspace・zeros・onesなど生成関数
数値計算では「規則的な配列」「初期値が決まった配列」を素早く用意する場面が多く、NumPy(python np)には用途別の生成関数が揃っています。代表例を使い分けられるようにしておくと、コードが簡潔になります。
np.arange(start, stop, step):一定間隔の数列(stopは基本的に含まない)np.linspace(start, stop, num):start〜stopを「指定個数」で等分(stopを含むのが基本)np.zeros(shape):0で埋めた配列np.ones(shape):1で埋めた配列np.full(shape, fill_value):任意の値で埋めた配列
import numpy as np
x1 = np.arange(0, 10, 2) # 0,2,4,6,8
x2 = np.linspace(0, 1, 5) # 0.0〜1.0 を5点で等分
z = np.zeros((2, 3)) # 2行3列を0で初期化
o = np.ones((2, 3)) # 2行3列を1で初期化
f = np.full((2, 3), 7) # 2行3列を7で初期化
print(x1) # [0 2 4 6 8]
print(x2) # [0. 0.25 0.5 0.75 1. ]
特にarangeとlinspaceは似ていますが、意図が異なります。刻み幅(step)で管理したいならarange、点の数(num)を固定したいならlinspaceが適しています。小数ステップをarangeで扱うと丸め誤差の影響が出ることがあるため、等分が目的ならlinspaceが安全です。
乱数配列の作成(random系)
テストデータ作成やシミュレーションでは乱数配列がよく必要になります。NumPyではnp.random配下に乱数生成機能がまとまっており、範囲指定の整数乱数や一様分布・正規分布などを手軽に作れます。
import numpy as np
# 0〜1の一様乱数(浮動小数)を 2x3 で生成
u = np.random.random((2, 3))
# 0以上10未満の整数乱数を 2x3 で生成
rint = np.random.randint(0, 10, size=(2, 3))
# 平均0、標準偏差1の正規分布乱数を 5個
n = np.random.normal(loc=0.0, scale=1.0, size=5)
print(u)
print(rint)
print(n)
同じ乱数列を再現したい場合は、シードを固定します。学習用サンプルや検証コードでは再現性が重要になるため、最初に設定しておくと安心です。
import numpy as np
np.random.seed(42)
x = np.random.randint(0, 10, size=5)
print(x)
shapeなど配列の形状・属性を確認する
ndarrayは「値」だけでなく、「形状(shape)」「次元数(ndim)」「要素数(size)」などの属性を持ちます。python npで配列計算を行う際、エラーや想定外の結果の多くは“形の勘違い”から起こるため、属性確認は必須スキルです。
arr.shape:各次元のサイズ(例:2行3列なら(2, 3))arr.ndim:次元数(1次元/2次元/…)arr.size:全要素数arr.itemsize:1要素あたりのバイト数arr.nbytes:配列全体のバイト数(size * itemsize)
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print(arr.shape) # (2, 3)
print(arr.ndim) # 2
print(arr.size) # 6
print(arr.itemsize) # dtypeに依存(例:int64なら8)
print(arr.nbytes) # 配列全体のメモリ量
形状が分かれば「行列として扱っているのか」「ベクトルとして扱っているのか」が明確になります。特に2次元以上のデータを作成した直後は、まずshapeを確認する癖を付けると、後工程が安定します。
dtype(データ型)と型の選び方
ndarrayのdtypeは「要素がどの型として格納されているか」を示します。NumPy(np)はC言語に近い固定長の型を使うため、Pythonの通常の数値よりもメモリ効率や計算性能の見通しが立ちやすいのが特徴です。一方で、型によって表現できる範囲や精度が異なるため、用途に応じた選択が重要になります。
まずは作成した配列の型を確認します。
import numpy as np
a = np.array([1, 2, 3])
b = np.array([1.0, 2.0, 3.0])
print(a.dtype) # int系(環境により int32/int64 など)
print(b.dtype) # float64 など
dtypeは明示指定もできます。たとえば、メモリを節約したい、型を固定して入出力仕様に合わせたい、といった場面で有効です。
import numpy as np
x = np.array([1, 2, 3], dtype=np.int32)
y = np.zeros((2, 3), dtype=np.float32)
print(x.dtype) # int32
print(y.dtype) # float32
型選びの目安としては、次の考え方が実務で役立ちます。
int系:カウント、ID、インデックスなど整数用途。範囲に注意(小さい型はオーバーフローの可能性)。float32:メモリ節約・高速化を優先したい数値計算でよく使う。精度はfloat64より低い。float64:精度重視の数値計算の標準的選択。Pythonの浮動小数点(通常は倍精度)とも相性がよい。bool:真偽値のマスクやフラグ用途に便利。
なお、異なる型が混在する入力からnp.arrayを作ると、より表現力の高い型に“昇格”して揃えられることがあります。意図したdtypeになっているかは、配列作成後にdtypeを確認しておくのが安全です。
配列の参照・抽出:インデックス/スライス/条件抽出

NumPy(np)の配列(ndarray)は、必要な要素だけを素早く取り出せるのが強みです。インデックス・スライス・条件抽出を使い分けることで、前処理や特徴量作成などの作業が一気に効率化します。ここでは「python np」で頻出の参照・抽出パターンを、基本から順に整理します。
整数インデックスで要素を取り出す
最も基本的なのが、整数インデックスによる参照です。1次元配列なら「何番目の要素か」、2次元以上なら「行・列(軸)の位置」を指定して取り出します。
import numpy as np
a = np.array([10, 20, 30, 40])
print(a[0]) # 10
print(a[2]) # 30
print(a[-1]) # 40(末尾)2次元配列では、各軸のインデックスをカンマ区切りで指定します(行→列の順が一般的です)。
m = np.array([[1, 2, 3],
[4, 5, 6]])
print(m[0, 1]) # 2(0行目の1列目)
print(m[1, -1]) # 6(1行目の最後の列)なお、m[0][1] のようにも書けますが、NumPyでは m[0, 1] の方が意図が明確で高速になりやすく、推奨される書き方です。
スライスで範囲を切り出す
連続した範囲を取り出すならスライスが便利です。Pythonのリストと同様に start:stop:step で指定し、stop は含まれない点が重要です。
a = np.array([0, 1, 2, 3, 4, 5])
print(a[1:4]) # [1 2 3]
print(a[:3]) # [0 1 2]
print(a[3:]) # [3 4 5]
print(a[::2]) # [0 2 4]
print(a[::-1]) # [5 4 3 2 1 0](逆順)2次元配列も、各軸ごとにスライスできます。
m = np.array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
# 上から2行、左から3列
print(m[:2, :3])
# [[1 2 3]
# [5 6 7]]注意:NumPyのスライスは多くの場合「コピー」ではなく「ビュー(参照)」です。切り出した配列を書き換えると元配列も変わることがあります。
a = np.array([10, 20, 30, 40])
b = a[1:3] # ビューになりやすい
b[0] = 999
print(a) # [ 10 999 30 40]元を変えずに扱いたい場合は、明示的に .copy() を使います。
c = a[1:3].copy()整数配列・インデックス配列による抽出(高度なインデックス)
飛び飛びの要素を取り出したい場合は、取り出したい位置を「整数配列(インデックス配列)」として渡す方法が便利です。これはスライスと違い、結果が「コピー」になるのが一般的です。
a = np.array([10, 20, 30, 40, 50])
idx = np.array([0, 3, 4])
print(a[idx]) # [10 40 50]2次元でも同様に、行や列を任意の順序で抽出できます。
m = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 0行目と2行目を抽出(順序も指定どおり)
print(m[[0, 2], :])
# [[1 2 3]
# [7 8 9]]さらに「(行インデックス, 列インデックス) を同時に指定して、特定の要素の組を抜き出す」こともできます。これは座標指定のように使えるため、python npでのデータ抽出で頻出です。
# (0,0), (1,2), (2,1) の要素を取り出す
rows = np.array([0, 1, 2])
cols = np.array([0, 2, 1])
print(m[rows, cols]) # [1 6 8]真理値(ブール)配列でフィルタする
条件に合う要素だけを抽出したいときは、ブール(True/False)配列によるフィルタが強力です。まず比較演算などで条件配列を作り、それをそのままインデックスとして渡します。
a = np.array([3, 10, 7, 2, 15])
mask = a >= 7
print(mask) # [False True True False True]
print(a[mask]) # [10 7 15]1行で書くことも多いです。
print(a[a < 5]) # [3 2]複数条件では、Pythonの and/or ではなく、NumPyの要素ごとの演算である &(AND)、|(OR)を使います。また、比較式は括弧で囲むのが安全です。
a = np.array([1, 5, 8, 10, 12])
print(a[(a >= 5) & (a <= 10)]) # [ 5 8 10]
print(a[(a < 3) | (a > 10)]) # [ 1 12]注意:a >= 5 & a <= 10 のように括弧なしで書くと、演算子の優先順位で意図しない結果やエラーになりやすいです。
2次元以上でも同じ考え方で、条件に合う要素だけを「フラットに」取り出せます(結果は1次元になりやすい点を覚えておくと混乱しません)。
m = np.array([[1, 2, 3],
[4, 5, 6]])
print(m[m % 2 == 0]) # [2 4 6]whereで条件分岐・置換を行う
np.where は「条件に応じて値を選ぶ/置き換える」ための定番関数です。フィルタ抽出(削って小さくする)ではなく、配列の形を保ったまま条件分岐したい場面で特に役立ちます。
代表的なのが、np.where(条件, 条件Trueのときの値, 条件Falseのときの値) の形です。
a = np.array([2, 5, 8, 1])
b = np.where(a >= 5, 1, 0) # 5以上なら1、それ以外は0
print(b) # [0 1 1 0]既存値を残しつつ、一部だけ置換することもできます。
a = np.array([100, -50, 30, -10])
# 負の値だけ0に置換(それ以外は元の値)
clipped = np.where(a < 0, 0, a)
print(clipped) # [100 0 30 0]文字列ラベル付けなども可能で、条件によるカテゴリ分けにも使えます。
a = np.array([45, 72, 90])
label = np.where(a >= 80, "A", "B")
print(label) # ['B' 'B' 'A']また、np.where(条件) と2引数・3引数を省略した形で使うと、「条件を満たす要素のインデックス」を返します(抽出ではなく位置の特定)。
a = np.array([0, 3, 0, 5, 0])
pos = np.where(a == 0)
print(pos) # (array([0, 2, 4]),)「python npで条件に合う要素の場所を知りたい」「条件で値を一括置換したい」といった用途では、ブールフィルタと並んでnp.whereが定番の選択肢になります。
配列計算の基本:要素ごとの演算とユニバーサル関数
NumPy(python np)での計算は、配列(ndarray)の「各要素に対して同じ処理を適用する」スタイルが基本です。for文で1つずつ回す代わりに、配列全体へまとめて演算を適用できるため、コードが短く読みやすくなり、実行も高速になりやすいのが特徴です。このセクションでは、要素ごとの四則演算、配列同士の要素単位演算、そしてユニバーサル関数(ufunc)の使いどころを整理します。
スカラと配列の四則演算
スカラ(単一の数値)と配列の四則演算は、配列の各要素に対してスカラ演算が適用されます。たとえば「全要素に10を足す」「全要素を2倍する」といった処理を、短い記述で表現できます。
import numpy as np
a = np.array([1, 2, 3])
a + 10 # array([11, 12, 13])
a - 1 # array([0, 1, 2])
a * 2 # array([2, 4, 6])
a / 2 # array([0.5, 1. , 1.5])注意点として、/ は「真の除算」になり、結果が浮動小数点(float)になることがあります。整数のまま割り算結果を得たい場合は //(切り捨て除算)を使います。
a // 2 # array([0, 1, 1])また、べき乗は ** で表現できます。
a ** 2 # array([1, 4, 9])配列同士の演算(要素単位)
NumPyの基本演算(+, -, *, /, ** など)は、同じ形状の配列同士であれば「同じ位置の要素どうし」を計算する要素単位(element-wise)の演算になります。これはリスト同士の演算とは大きく異なる点で、python np を使うメリットのひとつです。
x = np.array([1, 2, 3])
y = np.array([10, 20, 30])
x + y # array([11, 22, 33])
x * y # array([10, 40, 90])
y / x # array([10. , 10. , 10.])形状が一致しない場合は原則としてエラーになります(要素単位で対応付けられないためです)。
x = np.array([1, 2, 3])
z = np.array([10, 20])
# x + z # ValueError: operands could not be broadcast together ...「同じ形状での要素単位演算」が基本であることを押さえておくと、計算結果の意味を取り違えにくくなります。なお、同じ*でも「行列積」をしたい場合は別の演算(例:@)になりますが、ここでは要素単位演算に限定して理解するとスムーズです。
ユニバーサル関数(ufunc)の使いどころ
ユニバーサル関数(ufunc)は、配列の各要素に対して高速に同じ処理を適用するためのNumPy組み込み関数群です。四則演算だけでなく、指数・対数・三角関数・丸めなど、数値計算で頻出の処理が揃っています。要素単位での計算を「意図が伝わる形で」書けるため、可読性の面でも強力です。
代表的なufuncの例は以下のとおりです。
np.sqrt(平方根)np.exp(指数)np.log(自然対数)np.sin,np.cos(三角関数)np.abs(絶対値)np.round,np.floor,np.ceil(丸め)
たとえば、平方根や指数を配列に一括で適用できます。
a = np.array([1, 4, 9, 16])
np.sqrt(a) # array([1., 2., 3., 4.])
np.exp(a) # 要素ごとに指数関数を適用また、比較演算も要素単位で実行され、条件判定に使える配列(真偽値配列)が得られます。これもufunc的な「配列全体に同じ演算」という考え方の延長です。
a = np.array([1, 2, 3])
a > 1 # array([False, True, True])ufuncを使う主なメリットは、次の3点です。
- 配列の各要素へ一括適用でき、コードが短くなる
- 数値計算としての意図(例:平方根、対数)が明確になる
- Pythonのループ処理を避けやすく、実行が高速になりやすい
一方で、Python標準のmathモジュールの関数は基本的にスカラ向けで、ndarrayを直接渡すとエラーになることがあります。配列計算では、同種の処理はまずNumPyのufunc(例:np.sqrt)を選ぶのが定石です。
集計・統計:sum/max/min/meanなど頻出関数

Pythonで数値データを扱うとき、まず必要になるのが「合計」「平均」「最大」「最小」といった基本的な集計です。NumPy(python np)では、配列(ndarray)に対してこれらを高速に計算できる関数が揃っており、前処理や簡易分析の土台になります。このセクションでは、頻出の集計・統計関数と、行列(2次元以上)で重要になるaxis指定の考え方を押さえます。
基本統計量を求める(合計・平均・最大・最小)
NumPyの集計関数は、配列全体を対象に「1つの値(スカラー)」として結果を返すのが基本です。まずは、最小構成の例で使い方を確認しましょう。
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(np.sum(a)) # 合計
print(np.mean(a)) # 平均
print(np.max(a)) # 最大
print(np.min(a)) # 最小
上記はすべて「関数として呼ぶ」書き方ですが、ndarrayのメソッドとしても同様に使えます(どちらでもOKです)。
print(a.sum())
print(a.mean())
print(a.max())
print(a.min())
実務では、欠損値(NaN)が混ざるケースもあります。その場合、NaNを含むままmeanなどを実行すると結果がNaNになってしまうため、NaNを無視して集計したいときは np.nanmean / np.nansum / np.nanmax / np.nanmin を使うのが定番です。
b = np.array([1.0, np.nan, 3.0])
print(np.mean(b)) # nan
print(np.nanmean(b)) # 2.0(NaNを無視)
また、合計や平均などの計算では、データ型によっては丸めやオーバーフローの影響が出ることがあります。特に整数型の大量加算が心配な場合は、必要に応じて浮動小数へ変換してから集計する(例:a.astype(np.float64))など、dtypeを意識すると安定します。
軸(axis)指定で行列方向に集計する
2次元配列(表・行列)になると、「全体」ではなく「行ごと」「列ごと」に集計したい場面が増えます。ここで重要なのが axis 指定です。NumPyでは一般に、axis=0 は「行方向に縦へ集計(列ごとに集計)」、axis=1 は「列方向に横へ集計(行ごとに集計)」という理解が基本になります。
m = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(np.sum(m)) # 全要素の合計(スカラー)
print(np.sum(m, axis=0)) # 列ごとの合計(形状: (3,))
print(np.sum(m, axis=1)) # 行ごとの合計(形状: (2,))
max / min / mean も同様に axis を取れます。たとえば「各列の最大値」や「各行の平均」を簡潔に出せます。
print(np.max(m, axis=0)) # 列ごとの最大
print(np.min(m, axis=1)) # 行ごとの最小
print(np.mean(m, axis=0)) # 列ごとの平均
集計結果の形状(次元)が変わる点は、後続の計算でつまずきやすいポイントです。たとえば、axisを指定すると「その軸が潰れて」次元が1つ減ります。元の次元を保ったまま集計結果を扱いたい場合は keepdims=True が便利です。
col_sum = np.sum(m, axis=0, keepdims=True)
row_mean = np.mean(m, axis=1, keepdims=True)
print(col_sum.shape) # (1, 3)
print(row_mean.shape) # (2, 1)
このように、python np(NumPy)の集計関数は「何を集計するか(sum/max/min/mean)」に加えて、「どの方向に集計するか(axis)」をセットで押さえると、1次元から多次元まで一貫した感覚で使いこなせます。
形状操作と結合:reshape・append・concatenate

NumPy(np)で配列を扱うとき、計算そのものと同じくらい重要なのが「形状(shape)の調整」と「配列同士の結合」です。データを行列として解釈し直したり、列や行を追加したり、複数の配列をまとめたりする場面では、reshape・append・concatenateが頻出します。ここでは、それぞれの役割と使い分け、つまずきやすい注意点を整理します。
reshapeで配列の形を組み替える
np.reshape(またはndarray.reshape)は、要素数を変えずに配列の形状だけを組み替える操作です。1次元のデータを「行×列」の2次元にしたり、逆に2次元を1次元に戻したりと、データの並びを保ったまま見た目(shape)を変更できます。
基本のポイントは次の通りです。
- 要素数(
size)が一致する形状にしか変形できない -1を使うと、その次元のサイズを自動推定できる- 結果は「ビュー(参照)」になる場合があり、元配列とメモリを共有することがある(状況によりコピーになる)
import numpy as np
a = np.arange(12) # [0, 1, 2, ... , 11]
b = a.reshape(3, 4) # 3行4列に整形
c = a.reshape(-1, 6) # 行数を自動推定(この場合2行6列)
print(a.shape) # (12,)
print(b.shape) # (3, 4)
print(c.shape) # (2, 6)
要素数が合わない形状を指定するとエラーになります。たとえば要素数12の配列を(5, 3)にすることはできません。形状設計が合っているか不安な場合は、先にa.sizeと目標shapeの積を照合すると安全です。
appendで要素を追加する(注意点含む)
np.appendは、配列の末尾に要素(または配列)を追加して新しい配列を返す関数です。「追加」という名前ですが、Pythonリストのappendのようにインプレースで伸びるわけではなく、毎回新しい配列を作る(コピーが発生する)点が重要な注意点です。大量データでループしながらnp.appendを繰り返すと、処理が遅くなりやすいです。
axis指定の有無で挙動が変わります。
axis=None(デフォルト): 入力配列は一度1次元に平坦化されてから追加されるaxisを指定: 指定軸方向に追加され、形状整合が必要になる
import numpy as np
x = np.array([[1, 2],
[3, 4]])
# axis指定なし:平坦化されてから追加
y = np.append(x, [5, 6])
print(y) # [1 2 3 4 5 6]
print(y.shape) # (6,)
# axis=0:行方向に追加(追加する側も2列である必要がある)
z = np.append(x, [[5, 6]], axis=0)
print(z)
# [[1 2]
# [3 4]
# [5 6]]
よくある落とし穴は、axisを指定したのに追加する配列の次元が合わないケースです。たとえばaxis=0で行追加したいなら「(1, 列数)」のように2次元の形に揃える必要があります。形状が揃わないと例外になったり、意図せず平坦化される(axis未指定の場合)ため、追加前に.reshape(1, -1)などで整形すると安全です。
concatenateで配列を結合する
np.concatenateは、複数の配列を指定した軸方向に結合するための基本関数です。2つ以上の配列を「まとめて一つにする」操作では、appendよりも意図が明確で、複数配列を一括で扱える点が便利です。
使い方の基本は、結合したい配列をタプルやリストで渡し、axisで結合方向を決めます。
axis=0:縦方向(行方向)に結合(列数が一致している必要)axis=1:横方向(列方向)に結合(行数が一致している必要)axis=None:平坦化してから結合(1次元として連結)
import numpy as np
a = np.array([[1, 2],
[3, 4]])
b = np.array([[5, 6],
[7, 8]])
# axis=0:行方向に結合((2,2) + (2,2) => (4,2))
c0 = np.concatenate([a, b], axis=0)
# axis=1:列方向に結合((2,2) + (2,2) => (2,4))
c1 = np.concatenate([a, b], axis=1)
print(c0)
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
print(c1)
# [[1 2 5 6]
# [3 4 7 8]]
np.concatenateで重要なのは「結合しない軸のサイズが一致していること」です。たとえばaxis=0で結合するなら列数が一致している必要があります。形状が合わない場合は、先にreshapeで次元を揃える、または結合軸の設計を見直すのが基本です。
なお、配列を結合して新しい配列を作る以上、concatenateも結果の作成にコピーが伴います。ですが、複数配列をまとめて結合する意図を明確に表現でき、NumPy(np)コードの可読性を上げやすいのが利点です。
ソートと並べ替えの基礎

NumPy(python np)で配列を扱うとき、「データの順番を揃える」「特定の列(行)を基準に並べ替える」といったソート処理は頻出です。特に多次元配列では、“どの方向(軸)に対して”ソートするかを意識しないと、意図しない並びになります。この章では、sortで配列を並べ替える基本と、axis指定の考え方を整理します。
sortで配列を並べ替える(軸指定の考え方)
NumPyのソートには大きく分けて「配列そのものを並べ替えた結果を返す」np.sortと、「元の配列をその場で並べ替える」ndarray.sortがあります。どちらも既定では昇順で、多次元の場合はaxis(軸)で“どの方向に並べ替えるか”を指定します。
まずは1次元配列の基本です。1次元なら軸の概念に迷いにくく、単純に値が小さい順に並びます。
import numpy as np
a = np.array([3, 1, 2])
sorted_a = np.sort(a)
print(sorted_a) # [1 2 3]
print(a) # [3 1 2](np.sortは元配列を変更しない)
一方でndarray.sort()は元配列を書き換えます。データを保持したい場合は注意が必要です。
a = np.array([3, 1, 2])
a.sort()
print(a) # [1 2 3]
次に、多次元配列で重要になるaxis指定を見ていきます。axisは「どの軸に沿って並べ替えるか」を表し、2次元配列の場合は以下のイメージで捉えると理解しやすいです。
axis=0:縦方向(行方向に積み上がっている軸)に見て、各列ごとに並べ替えるaxis=1:横方向(列方向に並んでいる軸)に見て、各行ごとに並べ替える
例として、2次元配列をソートします。
x = np.array([
[3, 1, 2],
[9, 7, 8]
])
print(np.sort(x, axis=1))
# 各行をそれぞれソート(行内の並べ替え)
# [[1 2 3]
# [7 8 9]]
上はaxis=1なので、行ごとに「左から右」へ並べ替わります。ではaxis=0ではどうなるかというと、列ごとに「上から下」へ並べ替えます。
print(np.sort(x, axis=0))
# 各列をそれぞれソート(列内の並べ替え)
# [[3 1 2]
# [9 7 8]]
この例だと各列がすでに昇順(上が小さく下が大きい)になっているため、見た目の変化が少なくなります。axisの効果を確認したいときは、あえて上下の大小が入れ替わるデータにすると差が明確です。
y = np.array([
[5, 2, 9],
[1, 8, 3]
])
print(np.sort(y, axis=0))
# 列ごとに上から下へ昇順
# [[1 2 3]
# [5 8 9]]
print(np.sort(y, axis=1))
# 行ごとに左から右へ昇順
# [[2 5 9]
# [1 3 8]]
なお、axis=Noneを指定すると、多次元配列でもいったん全要素を1次元として扱ってソートします(形は1次元配列として返ります)。「全体の値だけを小さい順に並べたい」用途で有効です。
z = np.array([[3, 1], [4, 2]])
print(np.sort(z, axis=None)) # [1 2 3 4]
まとめると、python npでのソートは「sortは昇順が基本」「多次元はaxisで“行ごとか列ごとか”が決まる」「元配列を保持したいならnp.sort」の3点を押さえるのが近道です。特にaxisはデータ整形や前処理で結果を大きく左右するため、配列の形状とセットで確認しながら使うと失敗を減らせます。
行列計算と線形代数:dot・行列積・関連演算
python np(NumPy)を使うと、内積や行列積といった線形代数の基本演算をシンプルな記述で高速に実行できます。特に「dot」「行列積(@)」は登場頻度が高く、データ分析や機械学習の前処理・計算の土台になります。このセクションでは、dotの意味の切り替わり(1次元・2次元で挙動が変わる点)や、次元(shape)の見方、代表的な線形代数演算を整理して理解できるようにまとめます。
dotで内積/行列積を計算する
np.dotは、与える配列の次元によって「内積」や「行列積」を計算します。python npにおける最初の混乱ポイントになりやすいので、まずはパターンごとの意味を押さえましょう。
1次元配列(ベクトル)同士:内積(スカラー)
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.dot(a, b) # 1*4 + 2*5 + 3*6 = 32
2次元配列(行列)同士:行列積
A = np.array([[1, 2],
[3, 4]])
B = np.array([[10, 20],
[30, 40]])
np.dot(A, B)
# [[ 70 100]
# [150 220]]
2次元×1次元:行列×ベクトル(結果はベクトル)
x = np.array([1, 1])
np.dot(A, x) # [3, 7]
なお、python npでは「何を計算しているか」を明確にしたい場合、後述する行列積演算子@や、より一般的なテンソル積に対応するnp.matmulを使い分けるのが実務的です。特にdotは次元で意味が変わるため、意図が伝わりにくいケースがあります。
行列積の基本(演算子・次元の見方)
行列積は、NumPyでは主に@演算子(またはnp.matmul)で表します。@は「行列積をしている」ことがコードから直感的に読み取れるため、python npの実装では推奨される場面が多いです。
A @ B # 行列積
np.matmul(A, B) # 同等(多次元にも対応)
行列積が成立する条件は、「左の列数」と「右の行数」が一致することです。shapeで表すと次のルールになります。
A.shape == (m, n)B.shape == (n, p)- このとき
A @ Bの結果は(m, p)
例として、(2,3) と (3,4) を掛けると (2,4) になります。
A = np.random.randn(2, 3)
B = np.random.randn(3, 4)
C = A @ B
A.shape, B.shape, C.shape # (2, 3), (3, 4), (2, 4)
一方で、要素ごとの掛け算(Hadamard積)である*とは意味がまったく異なります。ここを混同すると結果の解釈が崩れるため注意が必要です。
A * B:同じshape同士で要素ごとに掛け算(行列積ではない)A @ B:shapeの内側次元を合わせる行列積
また、ベクトルの「縦」「横」を明示したい場合は、1次元配列のままだと曖昧になりやすいので、2次元に整形して考えるのが安全です。
x = np.array([1, 2, 3]) # shape: (3,)
x_col = x.reshape(-1, 1) # shape: (3, 1) 縦ベクトル
x_row = x.reshape(1, -1) # shape: (1, 3) 横ベクトル
線形代数系の代表的な演算の概要
python npで線形代数を扱う際は、np.linalg名前空間に代表的な演算がまとまっています。ここでは「何ができるか」を俯瞰し、用途と注意点をセットで押さえます。
- 転置:
A.T行と列を入れ替えます。行列積の次元合わせや、対称行列の確認などで頻出です。
- 逆行列:
np.linalg.inv(A)逆行列は存在しない(特異)場合があり、数値的にも不安定になり得ます。実務では「逆行列を明示的に作る」より「連立方程式を解く(solve)」が好まれます。
- 連立一次方程式の解:
np.linalg.solve(A, b)A x = bの形を直接解きます。逆行列計算を介するより安定・高速になりやすいのが利点です。 - 行列式:
np.linalg.det(A)行列が「どれくらい体積を伸縮させるか」の指標で、可逆性(detが0に近いか)を見る目安にもなります。
- ランク:
np.linalg.matrix_rank(A)独立な次元の数を表します。データの冗長性や、解が一意に定まるかの検討に使われます。
- 固有値・固有ベクトル:
np.linalg.eig(A)正方行列の重要な性質分解で、振る舞いの理解や次元削減の基礎概念として登場します(対象によっては
eighなどが使われます)。 - 特異値分解(SVD):
np.linalg.svd(A)行列を情報量の大きい方向に分解します。ノイズ除去・低ランク近似などの基礎となる演算です。
- ノルム:
np.linalg.norm(x)ベクトルの長さや行列の大きさを測ります。距離・誤差評価・正則化の直感理解にもつながります。
これらの演算は、入力shapeが想定通りかどうかで結果やエラーが大きく変わります。線形代数をpython npで扱うときは、「何次元の配列を渡しているか」「行列積の内側次元が合っているか」を常にshapeで確認する習慣が、最短での理解とバグ防止につながります。
データの保存と読み込み:np.save/np.loadによる永続化

NumPy(python np)で扱うndarrayは、計算途中の中間結果や前処理済みデータなど「そのまま再利用したい配列」が頻繁に登場します。毎回計算し直すのではなく、配列をファイルに保存して必要なときに読み込めるようにしておくと、処理時間の短縮や実験の再現性向上につながります。ここでは、NumPy標準の永続化手段であるnp.saveとnp.loadを使った保存・復元の基本を整理します。
np.saveの使い方
np.saveは、ndarrayをNumPy独自のバイナリ形式(拡張子.npy)で保存する関数です。テキスト(CSVなど)に比べて高速に読み書きでき、dtypeやshapeといった配列のメタ情報も保持できるため、python npでのデータ保存の定番手段として使われます。
主な引数(保存先・保存対象など)
np.saveの基本形は以下です。
np.save(file, arr, allow_pickle=True, fix_imports=True)file:保存先を指定します。ファイルパス(文字列)またはファイルオブジェクトを渡せます。
例:"data.npy"のように指定すると、通常はその名前で保存されます。拡張子.npyを付けない場合、NumPyが自動で付与します(例:"data"→data.npy)。arr:保存したい配列(ndarray)を指定します。allow_pickle:オブジェクト配列などをpickleで保存できるようにするかの設定です。一般的な数値配列(int,float等)なら意識する場面は多くありませんが、必要性がない限りはデータの安全性・取り回しの観点でむやみにオブジェクト配列を保存しない運用が無難です。
実務上は、まず「保存先のファイル名」と「保存したいndarray」を正しく渡せることが最重要です。これだけでshapeやdtypeを含めた形で、計算結果をそのまま保存できます。
np.loadの使い方
np.loadは、.npy(または複数配列をまとめた.npz)を読み込んで、ndarrayとして復元する関数です。保存時のshapeやdtypeが保持されるため、読み込んだ瞬間に「元の配列がそのまま戻る」点が強みです。
主な引数と戻り値
np.loadの代表的な形は以下です。
np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding="ASCII")file:読み込み元のファイルパス(文字列)またはファイルオブジェクトを指定します。mmap_mode:メモリマップのモードを指定します(例:"r")。巨大な配列を「必要な部分だけ読みたい」場合に有効で、メモリ使用量を抑えやすくなります。allow_pickle:pickleを含むデータを読み込むかどうかです。既定はFalseで、セキュリティ上の理由から必要な場合のみTrueにします(信頼できるファイルに限定するのが基本です)。
戻り値は、読み込むファイル形式により次のように変わります。
.npyを読み込む場合:戻り値はnumpy.ndarrayです。.npzを読み込む場合:複数配列が入ったコンテナ(キーで取り出す形式)が返ります。
保存・復元の最小サンプル
最後に、python npでの保存と読み込みの最小構成を示します。まず配列をnp.saveで保存し、次にnp.loadで復元して、shapeや中身が変わらないことを確認します。
import numpy as np
# 1) 保存したい配列を用意
x = np.array([[1, 2, 3],
[4, 5, 6]], dtype=np.int64)
# 2) .npyとして保存("sample.npy" が生成される)
np.save("sample.npy", x)
# 3) 読み込み(ndarrayとして復元)
x2 = np.load("sample.npy")
# 4) 確認
print(x2)
print(x2.shape, x2.dtype)この方法なら、数値配列の構造(shape)とデータ型(dtype)を保ったまま永続化できます。特に反復試行やデータ前処理の段階で、計算済み配列を素早く再利用したいケースに有効です。
機械学習・深層学習でNumPyが使われる理由

機械学習・深層学習は、学習データを数値として扱い、行列(多次元配列)の計算を何度も繰り返してモデルを最適化する分野です。そのため、Pythonで機械学習を行う現場では、import numpy as np の形でNumPy(np)を読み込み、数値計算の土台として活用するのが一般的です。ここでは「なぜNumPyが使われるのか」を、計算速度と機能面の2つの観点から整理します。
大量の数値計算を高速に回す基盤になるため
機械学習・深層学習では、パラメータ更新や損失計算などで、ベクトル・行列の演算を膨大な回数実行します。ここでPythonの標準リスト(list)を使って要素ごとにループ処理すると、処理が遅くなりがちです。一方、NumPyの配列(ndarray)は数値計算に特化しており、同じ計算でもより高速に処理できるよう設計されています。
ポイントは、NumPy(python np)が「まとめて計算する」思想を前提にしている点です。例えば、データを1要素ずつ足し引きするのではなく、配列全体に対して一括で演算を適用できます。これにより、以下のような処理が現実的な時間で回せるようになります。
- 学習データの正規化・標準化など、全サンプルに同じ変換を適用する処理
- ミニバッチ学習での行列演算(バッチサイズ×特徴量数の計算を繰り返す)
- 損失関数や評価指標の計算(大量の予測値と正解ラベルの比較)
深層学習フレームワーク(例:PyTorch、TensorFlow)自体は内部でGPUを使った計算も行えますが、学習の前後に行うデータ整形や軽量な検算、ベースライン実装ではNumPy演算が頻繁に登場します。「まずはnpで高速に回す」ことが、機械学習実装の基本体力になります。
前処理・特徴量作成・行列演算で関数が揃っているため
機械学習の精度は、モデル構造だけでなく「入力データをどう作るか(前処理・特徴量)」に大きく左右されます。NumPy(python np)には、前処理や特徴量作成で必要になる基本操作が一通り揃っており、学習データ作りの工程をシンプルに組み立てられます。
具体的には、次のような場面でNumPyの関数群が役立ちます。
- 欠損や異常値に対する処理:条件に応じた置換やマスク処理などを配列演算で表現しやすい
- スケーリング・変換:平均との差分、分散での割り算、対数変換などを一括計算できる
- 特徴量の組み立て:複数配列の結合、形状変更、特定列の抽出などを手早く行える
- 行列演算の下準備:次元(サンプル数×特徴量数)を揃え、学習で使う形に整える
また、機械学習で頻出の「行列として計算する」という発想とも相性が良く、線形回帰や分類のような基本モデルから、ニューラルネットワークの前段(入力テンソルの整形)まで、npでデータを扱えることが実装の分かりやすさにつながります。
このようにNumPyは、単なる便利ライブラリではなく、機械学習・深層学習に必要な「前処理→特徴量→行列計算」という流れを支える基盤として機能します。結果として、python npに慣れているほど、学習パイプラインの実装・検証・改善をスムーズに進めやすくなります。
NumPyを使った簡単な分析例:重回帰の流れを体験

ここでは、python np(Pythonでimport numpy as npとして使うNumPy)だけを使い、「重回帰(複数の説明変数から目的変数を予測する)」を数値計算として解く流れを体験します。機械学習ライブラリを使わずに、行列としてデータを整え、係数(回帰係数)を計算するイメージを掴むことが目的です。
入力データ行列と目的変数の作り方
重回帰では、説明変数をまとめた行列を X、予測したい値(目的変数)をベクトル y として用意します。ポイントは「形(shape)」で、NumPy配列(ndarray)として次のように揃えると後の計算がスムーズです。
X:形状が(サンプル数, 特徴量数)の2次元配列y:形状が(サンプル数,)(1次元)または(サンプル数, 1)(2次元列ベクトル)
また、切片(intercept)を含めたい場合は、先頭列に「1だけの列(バイアス項)」を追加するのが定番です。NumPyだけで作る最小例を示します。
import numpy as np
# 例:サンプル数 n=5、説明変数が2つ(x1, x2)
x1 = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
x2 = np.array([2.0, 1.0, 0.0, 1.0, 2.0])
# 目的変数 y(ここでは例として適当な数値を置く)
y = np.array([3.0, 4.0, 5.0, 6.0, 7.0])
# (n,) を (n,1) に揃えたい場合(行列として扱いやすい)
y_col = y.reshape(-1, 1)
# 説明変数を列として結合して X を作る:shape = (n, 2)
X = np.column_stack([x1, x2])
# 切片を入れるなら先頭に 1 の列を追加:shape = (n, 3)
X_with_bias = np.column_stack([np.ones(len(X)), X])
X.shape, y.shape, X_with_bias.shape
ここで重要なのは、X が「各行=1サンプル、各列=1特徴量」という並びになっていることです。たとえば「行と列を逆にしてしまう」など shape が崩れると、後述の行列計算(転置や逆行列など)が意図通りに動かなくなります。
なお、y は1次元のままでも解ける場合が多い一方で、行列式で整理して理解したいときは (n,1) の列ベクトル(y_col)に揃えると見通しが良くなります。
重回帰を数値計算として解くイメージ
重回帰は「係数を当てはめて、予測値が実測値に近くなるようにする」問題です。NumPyでの理解としては、次の線形モデルを置きます。
y ≈ Xβ
ここで β(ベータ)が求めたい回帰係数ベクトルです。誤差の二乗和が最小になる β は、(条件が整うとき)次の式で求められます。
β = (XᵀX)⁻¹ Xᵀ y
つまり「転置(X.T)」「行列積」「逆行列(または疑似逆行列)」といった線形代数の計算に落ちます。python np で実装すると、概ね次の流れです。
import numpy as np
# 先ほど作った X_with_bias と y_col を使う想定
X = X_with_bias
y = y_col
# 正規方程式:beta = (X^T X)^{-1} X^T y
XtX = X.T @ X
Xty = X.T @ y
beta = np.linalg.inv(XtX) @ Xty # shape: (特徴量数+1, 1)
beta
ただし、実務・学習の両面で押さえたいのは、逆行列を直接求めると数値的に不安定になったり、そもそも逆行列が存在しないケースがあるという点です。NumPyでは、同じ最小二乗解をより安定に求める方法が用意されています。
np.linalg.lstsq:最小二乗問題を解く(回帰に直結)np.linalg.pinv:疑似逆行列を使う(退化・多重共線性に比較的強い)
たとえば最小二乗として解くなら以下の形です。
# 最小二乗解(推奨されやすい解き方の一つ)
beta_lstsq, residuals, rank, s = np.linalg.lstsq(X, y, rcond=None)
beta_lstsq # 回帰係数
求めた係数 β を使えば、予測値 ŷ は行列積で一発です。
# 予測値 y_hat = X beta
y_hat = X @ beta_lstsq
# 誤差(残差)
residual = y - y_hat
この一連の流れを通すと、「重回帰=アルゴリズム」というより、データを行列に整えて、線形代数の数値計算(最小二乗)として係数を解くという見え方になります。NumPy(np)は、この“形を揃える→行列演算する→結果を確認する”という重回帰の芯を、最小限の道具で体験するのに適したライブラリです。
次に学ぶと役立つ周辺ライブラリ

Pythonで「python np(NumPy)」の基本操作に慣れてくると、次に重要になるのが周辺ライブラリとの連携です。NumPyは数値配列を高速に扱う“土台”として設計されているため、表データ処理・可視化・科学計算・機械学習といった実務で頻出の領域へスムーズにつなげられます。ここでは、次に学ぶと効果が大きい代表的なライブラリと、NumPyからの接続ポイントを整理します。
Pandas(表データ処理)へのつなげ方
Pandasは、CSVやExcelなどの「表データ」を扱うための定番ライブラリです。NumPy(np)は行列やベクトルといった“配列”が中心ですが、Pandasは列名・行名(インデックス)を持つため、ビジネスデータやログ分析の前処理が格段にやりやすくなります。とはいえ内部ではNumPy配列を活用しているため、両者は自然につながります。
つなげ方の要点は「NumPy配列 ⇔ DataFrame/Series の相互変換」と「欠損値や型の扱い」です。
- NumPy配列からDataFrameを作る:列名を付けて表として解釈できる
- DataFrameからNumPy配列を取り出す:学習アルゴリズム入力や高速演算に渡しやすい
- 欠損値(NaN):np.nanはPandasでも欠損の基本表現として使われる
- dtype(型):数値列・カテゴリ列などの型設計が前処理品質に直結する
import numpy as np
import pandas as pd
# python np(NumPy)で作った配列を表データにする
x = np.array([[1.0, 2.0],
[3.0, np.nan],
[5.0, 6.0]])
df = pd.DataFrame(x, columns=["feature1", "feature2"])
# DataFrame → NumPy配列(行列)に戻す
X = df.to_numpy() # または df.values(推奨はto_numpy)
この往復ができると、Pandasで「欠損処理・集計・カテゴリ処理」などを行い、最終的にNumPy配列にして次工程(可視化や機械学習)へ渡す、という実務の王道パイプラインを組めます。
Matplotlib(可視化)へのつなげ方
MatplotlibはPythonの可視化ライブラリの代表格で、NumPy配列をそのまま描画に使える点が強みです。python npで作ったデータ(1次元・2次元配列)をグラフにするだけで、分布・傾向・外れ値などが一気に理解しやすくなります。
NumPyからつなげるときは、主に次のようなパターンを押さえると実用的です。
- 折れ線(時系列や連続データ):xとyをnp配列で用意してplot
- 散布図(相関を見る):2つの特徴量配列をscatterへ
- ヒストグラム(分布を見る):1変数配列をhistへ
- 行列(画像・ヒートマップ):2次元配列をimshowへ
import numpy as np
import matplotlib.pyplot as plt
# NumPyでデータ生成(例:サイン波)
x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)
plt.plot(x, y)
plt.title("sin curve (python np + matplotlib)")
plt.xlabel("x")
plt.ylabel("sin(x)")
plt.show()
可視化は「計算結果が妥当か」「前処理が効いているか」を確認する最短ルートです。NumPyで配列計算→Matplotlibで即確認、という往復を習慣化すると、分析やモデル開発の手戻りを減らせます。
SciPy/scikit-learn(科学計算・機械学習)へのつなげ方
より高度な数値計算やアルゴリズムに進むなら、SciPyとscikit-learnが定番です。SciPyは最適化・統計・信号処理など「科学計算の道具箱」で、scikit-learnは「機械学習の実装を揃えた標準ライブラリ」です。どちらも入力としてNumPy配列(np.ndarray)を前提に設計されており、python npの知識がそのまま土台になります。
まずSciPyは、NumPyだけでは手間のかかる処理を“関数として提供”してくれます。NumPyでデータを整形し、SciPyの関数へ渡す流れが基本です。
- 最適化:目的関数を定義し、パラメータ探索を行う
- 統計:分布、検定、確率密度などを扱う
- 線形代数の拡張:より専門的な分解や疎行列など
一方scikit-learnは、NumPy配列(特徴量行列Xと目的変数y)を渡して学習・評価する設計が一貫しています。NumPyで「形状(サンプル数×特徴量数)を揃える」「欠損やスケールを整える」などの準備をしてから接続するイメージです。
- 入力:X(2次元のnp配列)、y(1次元のnp配列)
- 前処理:標準化・分割・特徴量変換など(多くがNumPy互換)
- 学習と推論:fit→predictの共通インターフェース
import numpy as np
from sklearn.linear_model import LinearRegression
# 例:NumPy配列をscikit-learnへ渡す(形状が重要)
X = np.array([[1.0, 2.0],
[2.0, 0.5],
[3.0, 1.5]])
y = np.array([10.0, 7.0, 12.0])
model = LinearRegression()
model.fit(X, y)
pred = model.predict(X)
このように、NumPy(python np)で配列を作り、整形し、周辺ライブラリへ渡す——という接続ができると、単なる「配列計算」から「分析・可視化・機械学習」へ一気に実務レベルへ拡張できます。

