NumPy

Python科学計算の基盤ライブラリ。多次元配列、線形代数、フーリエ変換、乱数生成機能を提供。ほぼ全てのPython科学計算ライブラリの依存関係として機能し、C言語レベルの高速計算を実現。

Python科学計算数値計算多次元配列数学

GitHub概要

numpy/numpy

The fundamental package for scientific computing with Python.

ホームページ:https://numpy.org
スター29,929
ウォッチ597
フォーク11,085
作成日:2010年9月13日
言語:Python
ライセンス:Other

トピックス

numpypython

スター履歴

numpy/numpy Star History
データ取得日時: 2025/7/16 11:10

フレームワーク

NumPy

概要

NumPyは、Python科学計算の基盤ライブラリです。

詳細

NumPy(Numerical Python)は2006年にTravis Oliphantによって開発された、Pythonにおける科学計算の核となるライブラリです。多次元配列操作と数値計算機能を提供し、ほぼ全てのPythonデータサイエンスライブラリの基礎として機能します。高速なN次元配列オブジェクト(ndarray)を中心とし、Cで実装された効率的な数値演算、線形代数、フーリエ変換、乱数生成などの機能を提供します。ブロードキャスト機能により、異なる形状の配列間での数学演算を直感的に実現でき、ベクトル化により純粋Pythonループより数十倍高速な処理を実現します。Pandas、scikit-learn、TensorFlow、PyTorchなどの主要データサイエンス・機械学習ライブラリが内部でNumPyを使用しており、Pythonデータサイエンスエコシステムの中核として絶対的な地位を占めています。数値解析、科学シミュレーション、画像処理、機械学習の前処理など幅広い分野で使用されています。

メリット・デメリット

メリット

  • 高速性: C実装による純粋Pythonより数十倍高速な処理
  • メモリ効率: 効率的なメモリ使用とキャッシュ最適化
  • ブロードキャスト: 異なる形状の配列間での自然な数学演算
  • 豊富な機能: 線形代数、フーリエ変換、統計関数など
  • エコシステムの中心: 他のライブラリとの高い互換性
  • 安定性: 長期間の開発による高い信頼性
  • オープンソース: 無料で使用可能なオープンソースライセンス

デメリット

  • メモリ制約: 大きな配列はメモリ上に一度に読み込み必要
  • シングルスレッド: マルチスレッド処理がデフォルトでは無効
  • データ型制約: 同一データ型の要素のみを保持可能
  • APIの複雑さ: 多機能のため初心者には学習コストが高い
  • GPU非対応: ネイティブではGPUアクセラレーション非対応
  • 文字列処理: 数値以外のデータ処理の制約

主要リンク

書き方の例

Hello World

import numpy as np

# NumPyのバージョン確認
print(f"NumPy version: {np.__version__}")

# 配列の作成
arr1 = np.array([1, 2, 3, 4, 5])
print(f"1次元配列: {arr1}")

# 2次元配列
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(f"2次元配列:\n{arr2}")

# 配列の情報
print(f"形状: {arr2.shape}")
print(f"次元数: {arr2.ndim}")
print(f"データ型: {arr2.dtype}")
print(f"要素数: {arr2.size}")

# 基本的な数学演算
result = arr1 * 2
print(f"スカラー乗算: {result}")

# 配列間の演算
arr3 = np.array([2, 2, 2, 2, 2])
print(f"配列間の加算: {arr1 + arr3}")
print(f"配列間の乗算: {arr1 * arr3}")

配列の作成と操作

import numpy as np

# 様々な方法で配列を作成

# ゼロで初期化
zeros = np.zeros((3, 4))
print(f"ゼロ配列:\n{zeros}")

# 1で初期化
ones = np.ones((2, 3, 2))
print(f"\n1配列の形状: {ones.shape}")

# 特定の値で初期化
filled = np.full((3, 3), 7)
print(f"\n7で埋めた配列:\n{filled}")

# 連続した値の配列
range_arr = np.arange(0, 10, 2)
print(f"\n等差数列: {range_arr}")

# 等間隔の配列
linspace_arr = np.linspace(0, 1, 5)
print(f"等間隔: {linspace_arr}")

# 単位行列
identity = np.eye(4)
print(f"\n単位行列:\n{identity}")

# 乱数配列
np.random.seed(42)  # 再現性のため
random_arr = np.random.random((3, 3))
print(f"\n乱数配列:\n{random_arr}")

# 正規分布の乱数
normal_arr = np.random.normal(0, 1, (2, 3))
print(f"\n正規分布乱数:\n{normal_arr}")

# 配列の形状変更
reshaped = range_arr.reshape(2, 2)
print(f"\n形状変更後:\n{reshaped}")

# 配列の連結
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
concatenated = np.concatenate([arr1, arr2])
print(f"\n連結: {concatenated}")

# スタック操作
stacked_v = np.vstack([arr1, arr2])  # 縦方向
stacked_h = np.hstack([arr1, arr2])  # 横方向
print(f"\n縦スタック:\n{stacked_v}")
print(f"横スタック: {stacked_h}")

数学演算と統計

import numpy as np

# サンプルデータ
np.random.seed(42)
data = np.random.normal(50, 15, (5, 4))
print(f"サンプルデータ:\n{data}")

# 基本統計
print(f"\n平均値: {np.mean(data):.2f}")
print(f"中央値: {np.median(data):.2f}")
print(f"標準偏差: {np.std(data):.2f}")
print(f"分散: {np.var(data):.2f}")
print(f"最小値: {np.min(data):.2f}")
print(f"最大値: {np.max(data):.2f}")

# 軸方向の統計
print(f"\n列方向の平均: {np.mean(data, axis=0)}")
print(f"行方向の平均: {np.mean(data, axis=1)}")

# 数学関数
angles = np.array([0, np.pi/4, np.pi/2, np.pi])
print(f"\n角度: {angles}")
print(f"sin値: {np.sin(angles)}")
print(f"cos値: {np.cos(angles)}")

# 指数、対数関数
x = np.array([1, 2, 3, 4, 5])
print(f"\n指数: {np.exp(x)}")
print(f"自然対数: {np.log(x)}")
print(f"底が10の対数: {np.log10(x)}")

# 累積和、累積積
print(f"\n累積和: {np.cumsum(x)}")
print(f"累積積: {np.cumprod(x)}")

# 丸め操作
float_data = np.array([1.23, 4.56, 7.89])
print(f"\n元データ: {float_data}")
print(f"四捨五入: {np.round(float_data, 1)}")
print(f"切り上げ: {np.ceil(float_data)}")
print(f"切り捨て: {np.floor(float_data)}")

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

import numpy as np

# 2次元配列の作成
arr = np.arange(24).reshape(4, 6)
print(f"2次元配列:\n{arr}")

# 基本インデックシング
print(f"\n要素 [0,0]: {arr[0, 0]}")
print(f"要素 [2,3]: {arr[2, 3]}")
print(f"最後の要素: {arr[-1, -1]}")

# 行・列の抽出
print(f"\n最初の行: {arr[0, :]}")
print(f"最初の列: {arr[:, 0]}")
print(f"最後の行: {arr[-1, :]}")

# スライシング
print(f"\n最初の2行: \n{arr[:2, :]}")
print(f"最初の3列: \n{arr[:, :3]}")
print(f"中央部分: \n{arr[1:3, 2:5]}")

# ステップ付きスライシング
print(f"\n1行おき: \n{arr[::2, :]}")
print(f"1列おき: \n{arr[:, ::2]}")
print(f"逆順: \n{arr[::-1, ::-1]}")

# 条件インデックシング
mask = arr > 10
print(f"\n10より大きい要素: {arr[mask]}")

# 複数条件
complex_mask = (arr > 5) & (arr < 15)
print(f"5から15の間の要素: {arr[complex_mask]}")

# where関数の使用
result = np.where(arr > 10, arr, 0)  # 10より大きい要素はそのまま、そうでなければ0
print(f"\nwhere結果:\n{result}")

# ファンシーインデックシング
rows = np.array([0, 2, 3])
cols = np.array([1, 3, 5])
print(f"\n指定位置の要素: {arr[rows, cols]}")

線形代数と行列演算

import numpy as np

# 行列の作成
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
B = np.array([[9, 8, 7],
              [6, 5, 4],
              [3, 2, 1]])

print(f"行列A:\n{A}")
print(f"\n行列B:\n{B}")

# 行列の加減算
print(f"\nA + B:\n{A + B}")
print(f"\nA - B:\n{A - B}")

# 行列の乗算(要素ごと)
print(f"\nA * B (要素ごと):\n{A * B}")

# 行列の乗算(数学的)
C = np.dot(A, B)
print(f"\nnp.dot(A, B):\n{C}")

# @ 演算子でも行列乗算
D = A @ B
print(f"\nA @ B:\n{D}")

# 転置
print(f"\nAの転置:\n{A.T}")

# 行列式
det_A = np.linalg.det(A)
print(f"\nAの行列式: {det_A:.6f}")

# 逆行列(正則行列の場合)
regular_matrix = np.array([[1, 2], [3, 4]])
inv_matrix = np.linalg.inv(regular_matrix)
print(f"\n正則行列:\n{regular_matrix}")
print(f"逆行列:\n{inv_matrix}")

# 固有値と固有ベクトル
eigenvalues, eigenvectors = np.linalg.eig(regular_matrix)
print(f"\n固有値: {eigenvalues}")
print(f"固有ベクトル:\n{eigenvectors}")

# 連立一次方程式の解
# Ax = b の形
coeff_matrix = np.array([[2, 1], [1, 3]])
constants = np.array([3, 4])
solution = np.linalg.solve(coeff_matrix, constants)
print(f"\n連立一次方程式の解: {solution}")

# ノルム
vector = np.array([3, 4])
print(f"\nベクトル: {vector}")
print(f"L2ノルム: {np.linalg.norm(vector)}")
print(f"L1ノルム: {np.linalg.norm(vector, 1)}")

ブロードキャストとベクトル化

import numpy as np

# ブロードキャストの例
print("ブロードキャストの例:")

# スカラーと配列
scalar = 5
array_1d = np.array([1, 2, 3, 4])
result1 = scalar * array_1d
print(f"スカラー * 1D配列: {result1}")

# 1D配列と2D配列
array_2d = np.array([[1, 2, 3, 4],
                     [5, 6, 7, 8]])
result2 = array_1d + array_2d
print(f"\n1D + 2D配列:\n{result2}")

# 異なる形状の配列
array_col = np.array([[1], [2]])  # (2, 1)
array_row = np.array([10, 20, 30])  # (3,)
result3 = array_col + array_row
print(f"\n列ベクトル + 行ベクトル:\n{result3}")

# ベクトル化の例
print("\n\nベクトル化の例:")

# 非ベクトル化版(遅い)
def slow_square(arr):
    result = []
    for x in arr:
        result.append(x**2)
    return np.array(result)

# ベクトル化版(高速)
def fast_square(arr):
    return arr**2

# パフォーマンス比較用データ
large_array = np.arange(1000000)

# 結果の確認
small_test = np.array([1, 2, 3, 4, 5])
print(f"元配列: {small_test}")
print(f"非ベクトル化: {slow_square(small_test)}")
print(f"ベクトル化: {fast_square(small_test)}")

# カスタム関数のベクトル化
def custom_function(x):
    return x**2 + 2*x + 1

# NumPyのベクトル化機能
vectorized_func = np.vectorize(custom_function)

test_array = np.array([1, 2, 3, 4])
print(f"\nカスタム関数のベクトル化: {vectorized_func(test_array)}")

# 普通のベクトル化(こちらの方が高速)
direct_result = test_array**2 + 2*test_array + 1
print(f"直接ベクトル化: {direct_result}")

ファイル入出力とデータ保存

import numpy as np

# サンプルデータの作成
data = np.random.rand(5, 3)
print(f"サンプルデータ:\n{data}")

# NumPyバイナリ形式で保存
# np.save('data.npy', data)
# loaded_data = np.load('data.npy')
# print(f"\n読み込みデータ:\n{loaded_data}")

# 複数の配列を保存
data2 = np.arange(10)
data3 = np.ones((2, 2))
# np.savez('multiple_arrays.npz', first=data, second=data2, third=data3)
# loaded_multiple = np.load('multiple_arrays.npz')
# print(f"\n複数配列のキー: {list(loaded_multiple.keys())}")

# テキスト形式で保存
# np.savetxt('data.txt', data, delimiter=',')
# loaded_text = np.loadtxt('data.txt', delimiter=',')
# print(f"\nテキストから読み込み:\n{loaded_text}")

# CSVで保存(ヘッダー付き)
header = 'col1,col2,col3'
# np.savetxt('data.csv', data, delimiter=',', header=header, comments='')

# メモリマッピングファイル(大きなファイル用)
# large_array = np.arange(1000000)
# np.save('large_file.npy', large_array)
# memory_mapped = np.load('large_file.npy', mmap_mode='r')  # 読み取り専用
# print(f"\nメモリマッピングファイルの形状: {memory_mapped.shape}")

print("ファイル操作はコメントアウトしています")

# バイトオーダーとデータ型の制御
array_int32 = np.array([1, 2, 3], dtype=np.int32)
array_float64 = np.array([1.0, 2.0, 3.0], dtype=np.float64)
print(f"\nint32配列: {array_int32}, dtype: {array_int32.dtype}")
print(f"float64配列: {array_float64}, dtype: {array_float64.dtype}")

# データ型の変換
converted = array_int32.astype(np.float32)
print(f"変換後: {converted}, dtype: {converted.dtype}")

# バイナリデータの直接操作
bytes_data = array_int32.tobytes()
print(f"\nバイトデータ長: {len(bytes_data)}")
restored = np.frombuffer(bytes_data, dtype=np.int32)
print(f"復元された配列: {restored}")