Python NumPy完全攻略【配列操作・数値計算を徹底マスター】

 

NumPy(Numerical Python)は、Pythonで数値計算を行うための最も重要なライブラリです。機械学習、データサイエンス、科学計算の基盤として広く使用されています。本記事では、NumPyの基本から応用まで、実用的なサンプルコードとともに徹底解説します。

NumPyとは

NumPyは、多次元配列オブジェクトと配列を操作するための関数群を提供するPythonライブラリです。主な特徴:

  • 高速な多次元配列操作
  • ブロードキャスティング機能
  • 線形代数関数
  • フーリエ変換
  • 乱数生成機能
  • C/C++/Fortranコードとの統合

インストールと基本設定

# NumPyのインストール
pip install numpy

# 数値計算関連ライブラリも一緒に
pip install numpy scipy matplotlib pandas
import numpy as np
print(np.__version__)  # バージョン確認

NumPy配列の基本

配列の作成

import numpy as np

# リストから配列作成
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr1)  # [1 2 3 4 5]
print(arr2.shape)  # (2, 3)

特殊な配列の生成

import numpy as np

# ゼロ配列、1配列
zeros = np.zeros((3, 4))
ones = np.ones((2, 3))
empty = np.empty((2, 2))

# 連続値、等間隔配列
range_arr = np.arange(0, 10, 2)  # [0 2 4 6 8]
linspace_arr = np.linspace(0, 1, 5)  # [0. 0.25 0.5 0.75 1.]

配列の属性

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(f"形状: {arr.shape}")      # (2, 3)
print(f"次元数: {arr.ndim}")     # 2
print(f"要素数: {arr.size}")     # 6
print(f"データ型: {arr.dtype}")  # int64

配列のインデックスとスライス

基本的なインデックス

import numpy as np

arr = np.array([10, 20, 30, 40, 50])
print(arr[0])    # 10
print(arr[-1])   # 50
print(arr[1:4])  # [20 30 40]

多次元配列のインデックス

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[0, 1])     # 2
print(arr[1, :])     # [4 5 6]
print(arr[:, 2])     # [3 6 9]
print(arr[0:2, 1:3]) # [[2 3] [5 6]]

ブール型インデックス

import numpy as np

arr = np.array([1, 2, 3, 4, 5, 6])
mask = arr > 3
print(arr[mask])  # [4 5 6]
print(arr[arr % 2 == 0])  # [2 4 6]

配列の形状操作

reshape(形状変更)

import numpy as np

arr = np.arange(12)
reshaped = arr.reshape(3, 4)
print(reshaped.shape)  # (3, 4)

# -1を使った自動計算
auto_shaped = arr.reshape(4, -1)  # (4, 3)

配列の結合と分割

import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# 結合
concat = np.concatenate([arr1, arr2])  # [1 2 3 4 5 6]
vstack = np.vstack([arr1, arr2])       # [[1 2 3] [4 5 6]]
hstack = np.hstack([arr1, arr2])       # [1 2 3 4 5 6]

# 分割
split_arr = np.split(np.arange(6), 3)  # [array([0, 1]), array([2, 3]), array([4, 5])]

数学関数と統計関数

基本的な数学関数

import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(np.sum(arr))    # 15
print(np.mean(arr))   # 3.0
print(np.std(arr))    # 1.4142135623730951
print(np.max(arr))    # 5
print(np.min(arr))    # 1

三角関数と指数関数

import numpy as np

angles = np.array([0, np.pi/4, np.pi/2, np.pi])
print(np.sin(angles))  # [0. 0.707 1. 0.]
print(np.cos(angles))  # [1. 0.707 0. -1.]

x = np.array([1, 2, 3])
print(np.exp(x))   # [2.718 7.389 20.086]
print(np.log(x))   # [0. 0.693 1.099]

軸を指定した統計計算

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(np.sum(arr, axis=0))    # [5 7 9] (縦方向の合計)
print(np.sum(arr, axis=1))    # [6 15] (横方向の合計)
print(np.mean(arr, axis=0))   # [2.5 3.5 4.5]

線形代数

行列の基本演算

import numpy as np

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

# 行列積
product = np.dot(A, B)  # または A @ B
print(product)  # [[19 22] [43 50]]

# 転置
transpose = A.T
print(transpose)  # [[1 3] [2 4]]

固有値と固有ベクトル

import numpy as np

A = np.array([[4, 2], [1, 3]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"固有値: {eigenvalues}")
print(f"固有ベクトル:\n{eigenvectors}")

連立方程式の解法

import numpy as np

# Ax = b の解を求める
A = np.array([[2, 1], [1, 3]])
b = np.array([8, 13])
x = np.linalg.solve(A, b)
print(x)  # [1. 6.]

ブロードキャスティング

基本的なブロードキャスティング

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
scalar = 10

# スカラーとの演算
result = arr + scalar  # [[11 12 13] [14 15 16]]
print(result)

# 異なる形状の配列との演算
vec = np.array([1, 2, 3])
result2 = arr + vec  # [[2 4 6] [5 7 9]]
print(result2)

高度なブロードキャスティング

import numpy as np

arr = np.arange(12).reshape(4, 3)
row_means = np.mean(arr, axis=1, keepdims=True)
centered = arr - row_means  # 各行の平均を引く
print(centered)

乱数生成

基本的な乱数生成

import numpy as np

# 0-1の一様分布
uniform = np.random.rand(3, 3)

# 標準正規分布
normal = np.random.randn(5)

# 整数の乱数
integers = np.random.randint(1, 100, size=10)
print(integers)

再現可能な乱数

import numpy as np

# シード設定
np.random.seed(42)
random_data = np.random.rand(5)
print(random_data)

# 新しいGeneratorを使用(推奨)
rng = np.random.default_rng(42)
random_data2 = rng.random(5)
print(random_data2)

実用的な応用例

データ分析での活用

import numpy as np

# 売上データの分析
sales = np.array([100, 150, 200, 180, 220, 190, 250])
print(f"平均売上: {np.mean(sales):.1f}")
print(f"売上の標準偏差: {np.std(sales):.1f}")
print(f"最大売上: {np.max(sales)}")
print(f"成長率: {(sales[-1] / sales[0] - 1) * 100:.1f}%")

画像処理での応用

import numpy as np

# 画像データのシミュレーション(グレースケール)
image = np.random.randint(0, 256, size=(100, 100), dtype=np.uint8)

# 画像の基本統計
print(f"画像サイズ: {image.shape}")
print(f"平均輝度: {np.mean(image):.1f}")
print(f"最大輝度: {np.max(image)}")

# 二値化
binary_image = (image > 128).astype(np.uint8) * 255

信号処理での応用

import numpy as np

# サイン波の生成
t = np.linspace(0, 2*np.pi, 1000)
signal = np.sin(5*t) + 0.5*np.sin(10*t)

# ノイズ追加
noisy_signal = signal + 0.1*np.random.randn(len(signal))

# 基本統計
print(f"信号の平均: {np.mean(signal):.3f}")
print(f"信号のRMS: {np.sqrt(np.mean(signal**2)):.3f}")

パフォーマンス最適化

ベクトル化の重要性

import numpy as np
import time

# 非効率な方法(Pythonループ)
def slow_sum(arr):
    result = 0
    for i in range(len(arr)):
        result += arr[i] ** 2
    return result

# 効率的な方法(NumPyベクトル化)
def fast_sum(arr):
    return np.sum(arr ** 2)

# 性能比較
large_array = np.random.rand(1000000)

start = time.time()
slow_result = slow_sum(large_array)
slow_time = time.time() - start

start = time.time()
fast_result = fast_sum(large_array)
fast_time = time.time() - start

print(f"遅い方法: {slow_time:.3f}秒")
print(f"速い方法: {fast_time:.3f}秒")
print(f"速度向上: {slow_time/fast_time:.1f}倍")

メモリ効率的な操作

import numpy as np

# in-place演算でメモリ節約
arr = np.random.rand(1000, 1000)
arr += 1  # arr = arr + 1 よりメモリ効率が良い
arr *= 2  # arr = arr * 2 よりメモリ効率が良い

# viewとcopyの使い分け
view = arr[::2, ::2]  # メモリを共有するview
copy = arr[::2, ::2].copy()  # 独立したcopy

高度な機能

構造化配列

import numpy as np

# 構造化配列の定義
dtype = [('name', 'U10'), ('age', 'i4'), ('salary', 'f8')]
employees = np.array([
    ('Alice', 25, 50000.0),
    ('Bob', 30, 60000.0),
    ('Charlie', 35, 70000.0)
], dtype=dtype)

print(employees['name'])    # ['Alice' 'Bob' 'Charlie']
print(employees['salary'])  # [50000. 60000. 70000.]

マスク配列

import numpy as np

# 欠損値を含むデータの処理
data = np.array([1, 2, -999, 4, 5, -999, 7])
masked_data = np.ma.masked_equal(data, -999)
print(f"平均: {np.ma.mean(masked_data):.1f}")  # -999を除外した平均

ユニバーサル関数(ufunc)

import numpy as np

# カスタムufuncの作成
def custom_func(x, y):
    return x**2 + y**2

vectorized_func = np.vectorize(custom_func)
result = vectorized_func([1, 2, 3], [4, 5, 6])
print(result)  # [17 29 45]

データ型と型変換

データ型の指定

import numpy as np

# 明示的なデータ型指定
int_arr = np.array([1, 2, 3], dtype=np.int32)
float_arr = np.array([1, 2, 3], dtype=np.float64)
bool_arr = np.array([True, False, True], dtype=np.bool_)

print(f"int32のサイズ: {int_arr.itemsize}バイト")
print(f"float64のサイズ: {float_arr.itemsize}バイト")

型変換

import numpy as np

arr = np.array([1.7, 2.8, 3.9])
int_arr = arr.astype(np.int32)    # [1 2 3]
str_arr = arr.astype(str)         # ['1.7' '2.8' '3.9']
print(int_arr)
print(str_arr)

ファイル入出力

NumPy形式での保存・読み込み

import numpy as np

# 配列の保存
arr = np.array([[1, 2, 3], [4, 5, 6]])
np.save('array.npy', arr)
np.savez('arrays.npz', a=arr, b=arr*2)  # 複数配列

# 配列の読み込み
loaded_arr = np.load('array.npy')
loaded_arrays = np.load('arrays.npz')
print(loaded_arrays['a'])

テキストファイルでの入出力

import numpy as np

# CSVファイルの読み込み
data = np.loadtxt('data.csv', delimiter=',', skiprows=1)

# データの保存
result = np.array([[1, 2, 3], [4, 5, 6]])
np.savetxt('output.csv', result, delimiter=',', fmt='%.2f')

エラーハンドリングとデバッグ

よくあるエラーと対処法

import numpy as np

try:
    # 形状不一致エラーの対処
    a = np.array([[1, 2], [3, 4]])
    b = np.array([1, 2, 3])
    result = a + b  # エラーが発生
except ValueError as e:
    print(f"形状エラー: {e}")
    b_reshaped = b[:2].reshape(-1, 1)  # 形状を調整
    result = a + b_reshaped
    print(result)

数値計算の注意点

import numpy as np

# 浮動小数点精度の問題
a = np.array([0.1, 0.2, 0.3])
print(np.sum(a) == 0.6)  # False

# 解決法:許容誤差を使った比較
print(np.allclose(np.sum(a), 0.6))  # True

# オーバーフロー対策
large_numbers = np.array([1e308, 1e308])
safe_sum = np.sum(large_numbers, dtype=np.float64)

パフォーマンス比較表

操作PythonリストNumPy配列速度向上
要素アクセス1x1x同等
数学演算1x10-100x大幅向上
メモリ使用量1x0.1-0.3x大幅削減
大量データ処理1x50-200x劇的向上

まとめ

NumPyは、Pythonで数値計算を行う際の必須ライブラリです。効率的な配列操作、豊富な数学関数、線形代数機能により、データサイエンスや機械学習の基盤となります。

重要なポイント:

  • ベクトル化でパフォーマンスを最大化
  • ブロードキャスティングで柔軟な配列操作
  • 適切なデータ型でメモリ効率を向上
  • in-place演算でメモリ使用量を削減

本記事のサンプルコードを参考に、NumPyを使った効率的な数値計算システムを構築してください。継続的な学習により、より高度なデータ処理技術を身につけることができます。

参考文献

  • NumPy公式ドキュメント
  • NumPy User Guide
  • Scientific Python Ecosystem
  • Linear Algebra with NumPy

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座