NumPy arange・linspaceの使い方完全マスター!連番・等差数列生成の決定版

 

NumPyで数値の配列を生成する際、最も頻繁に使用されるのがarange()linspace()関数です。本記事では、これらの関数の違いと使い分け、実践的な活用方法を豊富なサンプルコードとともに詳しく解説します。

arangeとlinspaceの基本的な違い

  • numpy.arange(): ステップ幅を指定して等差数列を生成
  • numpy.linspace(): 要素数を指定して等間隔の数列を生成
import numpy as np

# arange: ステップ0.5で0から3未満
arr1 = np.arange(0, 3, 0.5)
print("arange:", arr1)  # [0.  0.5 1.  1.5 2.  2.5]

# linspace: 0から3まで7個の等間隔点
arr2 = np.linspace(0, 3, 7)
print("linspace:", arr2)  # [0.  0.5 1.  1.5 2.  2.5 3. ]

1. numpy.arange() – ステップ指定の連番生成

1-1. 基本的な使用方法

# 整数の連番(0から9まで)
arr = np.arange(10)
print(arr)  # [0 1 2 3 4 5 6 7 8 9]

# 開始値と終了値を指定
arr = np.arange(2, 8)
print(arr)  # [2 3 4 5 6 7]

# ステップ幅を指定
arr = np.arange(0, 10, 2)
print(arr)  # [0 2 4 6 8]

1-2. 浮動小数点数での使用

# 小数のステップ
arr = np.arange(0, 2, 0.3)
print(arr)  # [0.  0.3 0.6 0.9 1.2 1.5 1.8]

# 負のステップ(降順)
arr = np.arange(5, 0, -1)
print(arr)  # [5 4 3 2 1]

# 小数での降順
arr = np.arange(1, 0, -0.2)
print(arr)  # [1.  0.8 0.6 0.4 0.2]

1-3. データ型の指定

# 整数型を明示的に指定
arr = np.arange(5, dtype=int)
print(arr, arr.dtype)  # [0 1 2 3 4] int64

# 浮動小数点型を指定
arr = np.arange(5, dtype=float)
print(arr, arr.dtype)  # [0. 1. 2. 3. 4.] float64

# 複素数型
arr = np.arange(3, dtype=complex)
print(arr)  # [0.+0.j 1.+0.j 2.+0.j]

2. numpy.linspace() – 要素数指定の等間隔生成

2-1. 基本的な使用方法

# 0から10まで11個の等間隔点
arr = np.linspace(0, 10, 11)
print(arr)  # [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]

# πの分割
arr = np.linspace(0, np.pi, 5)
print(arr)  # [0.         0.78539816 1.57079633 2.35619449 3.14159265]

# より細かい分割
arr = np.linspace(-1, 1, 9)
print(arr)  # [-1.   -0.75 -0.5  -0.25  0.    0.25  0.5   0.75  1.  ]

2-2. endpoint パラメータ

# 終点を含む(デフォルト)
arr1 = np.linspace(0, 1, 5, endpoint=True)
print("終点含む:", arr1)  # [0.   0.25 0.5  0.75 1.  ]

# 終点を含まない
arr2 = np.linspace(0, 1, 5, endpoint=False)
print("終点除く:", arr2)  # [0.  0.2 0.4 0.6 0.8]

2-3. retstep パラメータ

# ステップサイズも取得
arr, step = np.linspace(0, 10, 21, retstep=True)
print(f"配列の長さ: {len(arr)}")  # 21
print(f"ステップサイズ: {step}")   # 0.5
print(f"最初の3要素: {arr[:3]}")    # [0.  0.5 1. ]

3. 実践的な使い分けガイド

3-1. いつarangeを使うか

# インデックスとして使用
indices = np.arange(len(data))  # データ長に応じたインデックス

# 固定ステップでの繰り返し処理
for i in np.arange(0, 100, 5):  # 5ステップごと
    print(f"処理 {i}")

# 時系列データの生成(秒単位)
time_seconds = np.arange(0, 60, 0.1)  # 0.1秒間隔で1分間

3-2. いつlinspaceを使うか

# グラフのx軸生成
x = np.linspace(-np.pi, np.pi, 100)  # 滑らかな曲線用
y = np.sin(x)

# 分析範囲の等分割
analysis_points = np.linspace(min_val, max_val, 50)

# パラメータスイープ
learning_rates = np.linspace(0.001, 0.1, 20)  # 20個の学習率

4. 高度な活用例

4-1. 2次元グリッドの生成

# meshgridと組み合わせて2Dグリッド作成
x = np.linspace(-2, 2, 5)
y = np.linspace(-1, 1, 3)
X, Y = np.meshgrid(x, y)

print("X座標:")
print(X)
print("Y座標:")
print(Y)

4-2. 対数スケールとの組み合わせ

# 対数スケールでの等間隔
log_points = np.logspace(0, 2, 5)  # 10^0 から 10^2 まで
print("対数等間隔:", log_points)  # [  1.           3.16227766  10.          31.6227766  100.        ]

# linspaceで対数軸作成
log_x = np.linspace(np.log10(1), np.log10(100), 5)
linear_equiv = 10 ** log_x
print("同等結果:", linear_equiv)

4-3. 関数の数値積分での活用

def simpson_integration(func, a, b, n):
    """シンプソン法での数値積分"""
    if n % 2 == 1:
        n += 1  # 偶数に調整
    
    x = np.linspace(a, b, n+1)
    y = func(x)
    
    # シンプソン法の重み
    weights = np.ones(n+1)
    weights[1::2] = 4  # 奇数インデックス
    weights[2::2] = 2  # 偶数インデックス(端点除く)
    
    return (b - a) / (3 * n) * np.sum(weights * y)

# 使用例: sin(x)を0からπまで積分
result = simpson_integration(np.sin, 0, np.pi, 100)
print(f"∫sin(x)dx = {result:.6f}")  # 理論値は2

5. パフォーマンス比較と最適化

5-1. 速度比較

import time

# 大規模配列での速度比較
n = 1000000

# arangeの速度
start = time.time()
arr1 = np.arange(n)
time1 = time.time() - start

# linspaceの速度
start = time.time()
arr2 = np.linspace(0, n-1, n)
time2 = time.time() - start

print(f"arange: {time1:.6f}秒")
print(f"linspace: {time2:.6f}秒")
print(f"速度比: {time2/time1:.2f}倍")

5-2. メモリ効率的な生成

# 大規模配列でのメモリ効率
def memory_efficient_range(start, stop, step, chunk_size=10000):
    """メモリ効率的な大規模配列処理"""
    current = start
    while current < stop:
        end = min(current + chunk_size * step, stop)
        chunk = np.arange(current, end, step)
        yield chunk
        current = end

# 使用例
total_elements = 0
for chunk in memory_efficient_range(0, 1000000, 1, 50000):
    total_elements += len(chunk)
    # chunk単位での処理

print(f"処理した要素数: {total_elements}")

6. よくある問題と解決方法

6-1. 浮動小数点の精度問題

# 問題のあるコード
problematic = np.arange(0, 1, 0.1)
print("arange結果:", len(problematic))  # 期待値10だが実際は10

# 解決策1: linspaceを使用
solution1 = np.linspace(0, 1, 11)[:-1]  # 終点を除外
print("linspace解決:", len(solution1))

# 解決策2: 整数で計算後に変換
solution2 = np.arange(0, 10) * 0.1
print("整数変換解決:", len(solution2))

6-2. 空配列の回避

def safe_arange(start, stop, step):
    """安全なarange(空配列チェック付き)"""
    if (step > 0 and start >= stop) or (step < 0 and start <= stop):
        return np.array([])
    return np.arange(start, stop, step)

# テスト
result1 = safe_arange(5, 2, 1)    # 空配列
result2 = safe_arange(2, 5, 1)    # 正常
print("空配列回避1:", result1)
print("正常動作:", result2)

6-3. 型変換の問題

# 意図しない型変換の回避
def typed_arange(start, stop, step, dtype=None):
    """型を保持するarange"""
    result = np.arange(start, stop, step)
    if dtype is not None:
        result = result.astype(dtype)
    return result

# 使用例
int_range = typed_arange(0, 10, 1, dtype=int)
float_range = typed_arange(0, 10, 1, dtype=float)

print("整数型:", int_range.dtype)
print("浮動小数点型:", float_range.dtype)

7. 実用的なレシピ集

7-1. 時系列データの生成

def generate_time_series(start_date, periods, freq='D'):
    """時系列インデックスの生成"""
    if freq == 'D':  # 日次
        days = np.arange(periods)
        return [start_date + pd.Timedelta(days=d) for d in days]
    elif freq == 'H':  # 時間次
        hours = np.arange(periods)
        return [start_date + pd.Timedelta(hours=h) for h in hours]

# NumPyのみでの簡易版
def simple_time_range(hours):
    """時間の配列を生成(時間単位)"""
    return np.arange(0, hours, 0.5)  # 30分間隔

time_points = simple_time_range(24)  # 24時間分
print(f"時間点数: {len(time_points)}")

7-2. グラデーション配列の生成

def create_gradient(start_color, end_color, steps):
    """カラーグラデーション用の値生成"""
    r = np.linspace(start_color[0], end_color[0], steps)
    g = np.linspace(start_color[1], end_color[1], steps)
    b = np.linspace(start_color[2], end_color[2], steps)
    
    return np.column_stack([r, g, b])

# 赤から青へのグラデーション
gradient = create_gradient([255, 0, 0], [0, 0, 255], 10)
print("グラデーション(最初の3色):")
print(gradient[:3].astype(int))

7-3. サンプリング頻度の計算

def calculate_sampling_params(signal_freq, duration, min_points=100):
    """信号解析用のサンプリングパラメータ計算"""
    # ナイキスト周波数の2倍以上でサンプリング
    min_sampling_freq = 2.1 * signal_freq
    
    # 最小点数も考慮
    required_freq = max(min_sampling_freq, min_points / duration)
    
    # 実際のサンプリング点
    num_points = int(required_freq * duration)
    actual_freq = num_points / duration
    
    return {
        'num_points': num_points,
        'sampling_freq': actual_freq,
        'time_array': np.linspace(0, duration, num_points)
    }

# 100Hz信号を1秒間サンプリング
params = calculate_sampling_params(100, 1.0)
print(f"サンプリング点数: {params['num_points']}")
print(f"サンプリング周波数: {params['sampling_freq']:.1f} Hz")

8. データサイエンスでの活用

8-1. 特徴量の離散化

def discretize_feature(data, n_bins):
    """連続値特徴量の離散化"""
    min_val, max_val = data.min(), data.max()
    
    # ビン境界の生成
    bin_edges = np.linspace(min_val, max_val, n_bins + 1)
    
    # データを離散化
    digitized = np.digitize(data, bin_edges) - 1
    digitized = np.clip(digitized, 0, n_bins - 1)
    
    return digitized, bin_edges

# 使用例
data = np.random.normal(50, 15, 1000)
discrete_data, edges = discretize_feature(data, 5)
print(f"離散化前の範囲: [{data.min():.1f}, {data.max():.1f}]")
print(f"ビン数: {len(np.unique(discrete_data))}")

8-2. 交差検証用のインデックス生成

def generate_cv_indices(n_samples, n_folds=5):
    """交差検証用のインデックス生成"""
    indices = np.arange(n_samples)
    np.random.shuffle(indices)
    
    fold_sizes = np.full(n_folds, n_samples // n_folds)
    fold_sizes[:n_samples % n_folds] += 1
    
    folds = []
    start = 0
    for size in fold_sizes:
        folds.append(indices[start:start + size])
        start += size
    
    return folds

# 使用例
cv_folds = generate_cv_indices(100, 5)
print(f"フォールド数: {len(cv_folds)}")
print(f"各フォールドサイズ: {[len(fold) for fold in cv_folds]}")

まとめ

NumPyのarange()linspace()を適切に使い分けることで、効率的な数値計算が可能になります。

選択の指針:

  • 固定ステップが重要arange()
  • 要素数が重要linspace()
  • 浮動小数点の精密性が必要linspace()
  • 整数インデックスarange()

これらの関数をマスターして、データサイエンス、科学計算、機械学習プロジェクトを効率的に進めましょう!

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

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

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

■テックジム東京本校

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

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

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

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