閉じる

NumPyの基本操作まとめ: 配列作成/整形/演算を徹底解説

Pythonで高速な数値計算や多次元配列を扱うならNumPyが定番です。

配列の作成から整形、演算、統計、行列計算、NaNの扱いまで、よく使う操作を初心者向けに体系立てて解説します。

サンプルコードは最小限で実行可能な形にし、出力例も併記して理解を助けます。

NumPyとは何か

NumPyはPythonで数値計算を高速に行うためのライブラリです。

Pythonのリストよりもメモリ効率が良く、C言語に近い速度でベクトル化された演算ができます。

データ分析や機械学習の土台として、pandasやscikit-learn、TensorFlowなどの内部でも広く使われています。

導入方法

pipでインストールします。

一般にnumpynpという別名でインポートします。

Shell
# NumPyのインストール
pip install numpy
Python
# バージョンとエイリアスの確認
import numpy as np
print(np.__name__)
print(np.__version__)  # 実行環境により値は異なります
実行結果
numpy
(例) 2.3.3

ndarrayの基本

NumPyの中心はndarrayと呼ばれるN次元配列です。

要素の型(cst-code>dtype)が配列全体で統一され、固定長かつ連続領域に配置されます。

これにより、低レベル最適化が効き、高速に処理できます。

以下はPythonのリストとNumPy配列の挙動の違いを示す例です。

Python
# リストとNumPy配列の*演算の違い
import numpy as np

py_list = [1, 2, 3]
np_arr = np.array([1, 2, 3], dtype=np.int64)

# リストは要素の複製、NumPy配列は数値のスカラー倍
print(py_list * 2)
print(np_arr * 2)
実行結果
[1, 2, 3, 1, 2, 3]
[2 4 6]

よく使う属性

ndarrayには配列の形や型を知るための属性が用意されています。

代表的なものをまとめます。

属性意味
shape各次元のサイズ(タプル)(3, 4) なら3行4列
ndim次元数2は2次元配列
size要素総数shapeの積
dtype要素のデータ型int64やfloat64など
itemsize要素1つのバイト数int64なら8
nbytes配列全体のバイト数itemsize×size
strides次元ごとのバイトステップC順序なら(列数×itemsize, itemsize)
Python
import numpy as np

a = np.arange(12, dtype=np.int64).reshape(3, 4)
print(a)
print("shape:", a.shape)
print("ndim:", a.ndim)
print("size:", a.size)
print("dtype:", a.dtype)
print("itemsize:", a.itemsize)
print("nbytes:", a.nbytes)
print("strides:", a.strides)
実行結果
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
shape: (3, 4)
ndim: 2
size: 12
dtype: int64
itemsize: 8
nbytes: 96
strides: (32, 8)

配列の作成

NumPyでは、Pythonのリストやタプルから作る方法に加え、ゼロ配列や連番、乱数、型指定など多彩な作成手段があります。

リストから配列を作る

最も基本的なのはnp.arrayです。

多次元は入れ子のリストで表現します。

Python
import numpy as np

arr1d = np.array([1, 2, 3], dtype=np.int64)
arr2d = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)

print(arr1d)
print(type(arr1d))
print(arr2d)
print("shape:", arr2d.shape, "dtype:", arr2d.dtype)
実行結果
[1 2 3]
<class 'numpy.ndarray'>
[[1. 2. 3.]
 [4. 5. 6.]]
shape: (2, 3) dtype: float32

ゼロ/ワン/定数配列

np.zerosnp.onesnp.fullで初期化した配列を作れます。

np.emptyは中身が未初期化なので注意します。

Python
import numpy as np

z = np.zeros((2, 3), dtype=np.int32)
o = np.ones(4, dtype=np.float64)
f = np.full((2, 2), fill_value=7, dtype=np.int64)

print(z)
print(o)
print(f)
実行結果
[[0 0 0]
 [0 0 0]]
[1. 1. 1. 1.]
[[7 7]
 [7 7]]

連番と範囲

整数の等間隔にはnp.arange、指定した区間を分割した浮動小数にはnp.linspaceが便利です。

浮動小数の等差でarangeを使うと誤差で端がズレるため、区間分割が目的ならlinspaceを推奨します。

Python
import numpy as np

a = np.arange(0, 10, 2, dtype=np.int64)  # 0,2,4,6,8
b = np.linspace(0.0, 1.0, 5, dtype=np.float64)  # 0.0から1.0を5分割
c = np.arange(1, 13, dtype=np.int64).reshape(3, 4)  # 3行4列に整形

print(a)
print(b)
print(c)
実行結果
[0 2 4 6 8]
[0.   0.25 0.5  0.75 1.  ]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

乱数配列を作る

新しい推奨APIはnp.random.default_rngで生成器を作る方法です。

シードを固定すると再現性が得られます。

Python
import numpy as np

rng = np.random.default_rng(seed=42)

# 一様乱数(0以上1未満)
u = rng.random((2, 3))  # float64が既定
# 整数乱数(0〜9)
ri = rng.integers(0, 10, size=(2, 3), endpoint=False)
# 正規分布(平均0, 標準偏差1)
g = rng.normal(loc=0.0, scale=1.0, size=(3,))

print("u shape/dtype:", u.shape, u.dtype)
print("ri shape/dtype:", ri.shape, ri.dtype)
print("g shape/dtype:", g.shape, g.dtype)
実行結果
u shape/dtype: (2, 3) float64
ri shape/dtype: (2, 3) int64
g shape/dtype: (3,) float64

型の指定と変換

配列全体で同じdtypeを持ちます

作成時にdtype=...で指定、変換はastypeです。

Python
import numpy as np

x = np.array([1, 2, 3], dtype=np.int32)
xf = x.astype(np.float64)  # 安全な型拡張

y = np.array([1.2, 2.7, 3.5], dtype=np.float64)
y_trunc = y.astype(np.int64)  # 小数部は切り捨て
y_round = np.round(y).astype(np.int64)  # 四捨五入してから整数化

wrap = np.array([300])  # 256で循環(オーバーフローに注意)

print(x.dtype, xf.dtype)
print(y_trunc, y_round)
print(wrap, wrap.dtype)
実行結果
int32 float64
[1 2 3] [1 3 4]
[44] uint8

注意: 整数型でのオーバーフローは例外ではなく桁あふれになります。

必要に応じて十分なビット幅の型を選んでください。

配列の整形と取り出し

配列から必要な部分を取り出し、形状を柔軟に変える操作はNumPyの要です。

インデックスとスライス

1次元ではPythonのスライスと同様に動作します。

2次元以上は[行, 列]の順です。

Python
import numpy as np

v = np.arange(10, dtype=np.int64)
print(v)
print(v[0], v[-1])         # 先頭と末尾
print(v[2:8:2])            # 2から7まで2刻み
print(v[:3], v[7:])        # 先頭3つと後ろ3つ

m = np.arange(1, 13, dtype=np.int64).reshape(3, 4)
print(m)
print(m[1, 2])             # 2行目3列目(0始まり)
print(m[0, :])             # 1行目
print(m[:, -1])            # 最終列
print(m[0:2, 2:])          # 左上の部分切り出し
実行結果
[0 1 2 3 4 5 6 7 8 9]
0 9
[2 4 6]
[0 1 2] [7 8 9]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
7
[1 2 3 4]
[ 4  8 12]
[[3 4]
 [7 8]]

形状の変更

reshapeで形を変えられます。

-1は自動計算です。

Python
import numpy as np

a = np.arange(12, dtype=np.int64)
print(a.reshape(3, 4))
print(a.reshape(2, 3, 2))
print(a.reshape(-1, 6))  # 要素数が一致する限り-1で自動補完
実行結果
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[[ 0  1]
  [ 2  3]
  [ 4  5]]

 [[ 6  7]
  [ 8  9]
  [10 11]]]
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]

次元の追加/削除

次元の追加はnp.newaxis(またはNone)やnp.expand_dims、削除はnp.squeezeです。

Python
import numpy as np

v = np.array([10, 20, 30], dtype=np.int64)
row = v[np.newaxis, :]        # (1, 3)
col = v[:, np.newaxis]        # (3, 1)
sqz = np.squeeze(np.array([[[1], [2], [3]]], dtype=np.int64))  # (3,)

print(row, row.shape)
print(col, col.shape)
print(sqz, sqz.shape)
実行結果
[[10 20 30]] (1, 3)
[[10]
 [20]
 [30]] (3, 1)
[1 2 3] (3,)

転置と軸の入れ替え

2次元は.Tで転置、n次元はnp.transposenp.swapaxesが使えます。

Python
import numpy as np

M = np.arange(6, dtype=np.int64).reshape(2, 3)
print(M)
print(M.T)  # 転置(3, 2)

A = np.arange(24, dtype=np.int64).reshape(2, 3, 4)
B = np.transpose(A, (1, 0, 2))  # 軸0と1を入れ替え
print("A shape:", A.shape, "B shape:", B.shape)
実行結果
[[0 1 2]
 [3 4 5]]
[[0 3]
 [1 4]
 [2 5]]
A shape: (2, 3, 4) B shape: (3, 2, 4)

配列の結合/分割

np.concatenatenp.stackで結合、np.splitnp.array_splitで分割します。

Python
import numpy as np

a = np.arange(6, dtype=np.int64).reshape(2, 3)
b = np.arange(6, 12, dtype=np.int64).reshape(2, 3)

vcat = np.concatenate([a, b], axis=0)  # 縦結合(行方向)
hcat = np.concatenate([a, b], axis=1)  # 横結合(列方向)
stk = np.stack([a, b], axis=0)         # 新しい次元を追加して結合

s1, s2 = np.array_split(vcat, 2, axis=0)  # 行方向に2分割

print(vcat)
print(hcat)
print(stk.shape)  # (2, 2, 3)
print(s1)
print(s2)
実行結果
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
[[ 0  1  2  6  7  8]
 [ 3  4  5  9 10 11]]
(2, 2, 3)
[[0 1 2]
 [3 4 5]]
[[ 6  7  8]
 [ 9 10 11]]

配列の演算と集計

NumPyのベクトル化により、ループを書かずに全要素へ演算を適用できます。

要素ごとの演算とufunc

四則演算や三角関数などはufuncと呼ばれる高速関数で実装されています。

Python
import numpy as np

x = np.array([1, 2, 3], dtype=np.int64)
y = np.array([10, 20, 30], dtype=np.int64)

print(x + y)                 # 要素ごとの加算
print(np.add(x, y))          # 同じ意味
out = np.empty_like(x)
np.multiply(x, y, out=out)   # 結果を書き込み(メモリ再利用)
print(out)
print(np.sqrt(np.array([1.0, 4.0, 9.0], dtype=np.float64)))  # べき乗や根も高速
実行結果
[11 22 33]
[11 22 33]
[10 40 90]
[1. 2. 3.]

ブロードキャストの基本

サイズの異なる配列でも形状が互換なら自動的に拡張して演算します。

右側から次元を照合し、1または同じサイズなら一致とみなします。

Python
import numpy as np

A = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)  # (2, 3)
b = np.array([10, 20, 30], dtype=np.int64)            # (3,)
c = np.array([[100], [200]], dtype=np.int64)          # (2, 1)
s = 5                                                 # スカラー

print(A + b)  # (2,3)+(3,) -> (2,3)
print(A + c)  # (2,3)+(2,1) -> (2,3)
print(A + s)  # (2,3)+() -> (2,3)
実行結果
[[11 22 33]
 [14 25 36]]
[[101 102 103]
 [204 205 206]]
[[ 6  7  8]
 [ 9 10 11]]

互換でない形状はValueErrorになります。

必要ならnp.newaxisで次元を追加して整えます。

比較/論理/マスク抽出

条件で要素を選ぶ場合、比較演算とブール配列(マスク)を使います。

Python
import numpy as np

A = np.arange(1, 10, dtype=np.int64).reshape(3, 3)
mask_even = (A % 2 == 0)

print(A)
print(mask_even)                     # 偶数の位置
print(A[mask_even])                  # マスク抽出
mask_range = (A > 3) & (A < 8)       # 複数条件(論理積)
print(A[mask_range])                 # 条件に合う要素のみ
print(np.where(mask_even, A, -1))    # 条件式の分岐
print((A > 5).any(axis=1))           # 行ごとに1つでもTrueがあるか
実行結果
[[1 2 3]
 [4 5 6]
 [7 8 9]]
[[False  True False]
 [ True False  True]
 [False  True False]]
[2 4 6 8]
[4 5 6 7]
[[-1  2 -1]
 [ 4 -1  6]
 [ 7  8  9]]
[False  True  True]

基本統計

和や平均、標準偏差などはaxisで方向を指定できます。

Python
import numpy as np

data = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64)
print("sum:", data.sum())
print("mean:", data.mean())
print("std:", data.std())                # 母標準偏差(ddof=0)
print("sum axis=0:", data.sum(axis=0))   # 列ごと
print("sum axis=1:", data.sum(axis=1))   # 行ごと
print("argmax axis=0:", data.argmax(axis=0))  # 列ごとの最大の位置
実行結果
sum: 21.0
mean: 3.5
std: 1.707825127659933
sum axis=0: [5. 7. 9.]
sum axis=1: [ 6. 15.]
argmax axis=0: [1 1 1]

平均や標準偏差は浮動小数の丸め誤差の影響を受けるため、必要に応じてdtype=np.float64を用いましょう。

行列計算

行列積は@演算子またはnp.matmulが使えます。

線形代数はnp.linalgにまとまっています。

Python
import numpy as np

A = np.array([[1, 2], [3, 4]], dtype=np.float64)
B = np.array([[5, 6], [7, 8]], dtype=np.float64)

print("A@B =\n", A @ B)                 # 行列積
print("det(A) =", np.linalg.det(A))     # 行列式
print("inv(A) =\n", np.linalg.inv(A))   # 逆行列

b = np.array([1.0, 0.0], dtype=np.float64)
x = np.linalg.solve(A, b)               # 連立一次方程式 A x = b
print("solve(A, b) =", x)
実行結果
A@B =
 [[19. 22.]
 [43. 50.]]
det(A) = -2.0000000000000004
inv(A) =
 [[-2.   1. ]
 [ 1.5 -0.5]]
solve(A, b) = [-2.   1.5]
注意

特異行列(逆行列がない)に対してinvやsolveを呼ぶとエラーになります。

条件数が大きい場合は数値的に不安定なこともあります。

NaNへの対処

欠損や未定義の値はnp.nanで表現されます。

通常の統計関数はNaNを伝播させるため、np.nanmeanなどNaN無視版を使うか、事前に埋めます。

Python
import numpy as np

a = np.array([1.0, np.nan, 3.0, np.nan, 5.0], dtype=np.float64)
print("isnan:", np.isnan(a))
print("nanmean:", np.nanmean(a))  # 1,3,5の平均=3.0

filled = np.where(np.isnan(a), np.nanmean(a), a)  # 平均で埋める
print("filled:", filled)

# 無限大やNaNを有限値に置換
b = np.array([np.nan, np.inf, -np.inf, 2.0], dtype=np.float64)
print(np.nan_to_num(b, nan=0.0, posinf=1e9, neginf=-1e9))
実行結果
isnan: [False  True False  True False]
nanmean: 3.0
filled: [1. 3. 3. 3. 5.]
[ 0.e+00  1.e+09 -1.e+09  2.e+00]

NaN判定にはnp.isnan、有限判定にはnp.isfiniteが有用です。

まとめ

本記事ではNumPyの基礎として、配列(ndarray)の作成、整形、取り出し、要素演算、ブロードキャスト、条件抽出、統計、行列計算、NaN対処までを通して解説しました。

Pythonのリストでは難しい大規模データの高速処理も、NumPyならベクトル化axisの理解で簡潔に書けます。

はじめはnp.arrayreshapesum/mean@wherenanmeanといった基本から手を動かし、必要に応じて型(dtype)やブロードキャストの整合を意識するとつまずきにくくなります。

次のステップとしてはpandasや可視化(Matplotlib/Seaborn)と組み合わせて、実データ分析に適用してみてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!