NumPy配列を同じ値で初期化する全手法!zeros・ones・full・fill完全マスターガイド

 

NumPyで全ての要素を同じ値で初期化した配列を生成することは、データ分析や科学計算の基本操作です。本記事では、zeros()ones()full()fill()などの関数を使った様々な初期化方法を、実践的なサンプルコードとともに詳しく解説します。

初期化関数の全体像

NumPyには全要素を同じ値で初期化する複数の関数があります。

import numpy as np

# 基本的な初期化関数の比較
arr_zeros = np.zeros(5)           # 0で初期化
arr_ones = np.ones(5)             # 1で初期化
arr_full = np.full(5, 99)         # 任意の値(99)で初期化

print("zeros:", arr_zeros)        # [0. 0. 0. 0. 0.]
print("ones:", arr_ones)          # [1. 1. 1. 1. 1.]
print("full:", arr_full)          # [99 99 99 99 99]

選択の指針:

  • 0で初期化np.zeros()
  • 1で初期化np.ones()
  • 任意の値で初期化np.full()
  • 既存配列の値変更array.fill()

1. numpy.zeros() – ゼロ初期化配列

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

# 1次元ゼロ配列
zeros_1d = np.zeros(5)
print("1次元:", zeros_1d)         # [0. 0. 0. 0. 0.]

# 2次元ゼロ配列
zeros_2d = np.zeros((3, 4))
print("2次元形状:", zeros_2d.shape)  # (3, 4)

# 3次元ゼロ配列
zeros_3d = np.zeros((2, 3, 4))
print("3次元形状:", zeros_3d.shape)  # (2, 3, 4)

1-2. データ型の指定

# 整数型
int_zeros = np.zeros(5, dtype=int)
print("整数型:", int_zeros.dtype)    # int64

# 浮動小数点型(デフォルト)
float_zeros = np.zeros(5, dtype=float)
print("浮動小数点型:", float_zeros.dtype)  # float64

# 真偽値型
bool_zeros = np.zeros(5, dtype=bool)
print("真偽値型:", bool_zeros)       # [False False False False False]

# 複素数型
complex_zeros = np.zeros(3, dtype=complex)
print("複素数型:", complex_zeros)    # [0.+0.j 0.+0.j 0.+0.j]

1-3. メモリレイアウトとその他のオプション

# C順序(行優先、デフォルト)
c_zeros = np.zeros((3, 4), order='C')
print("C順序 strides:", c_zeros.strides)

# Fortran順序(列優先)
f_zeros = np.zeros((3, 4), order='F')
print("F順序 strides:", f_zeros.strides)

# メモリ使用量の確認
print(f"メモリ使用量: {c_zeros.nbytes} bytes")

2. numpy.ones() – 1初期化配列

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

# 1次元1配列
ones_1d = np.ones(6)
print("1次元:", ones_1d)            # [1. 1. 1. 1. 1. 1.]

# 2次元1配列
ones_2d = np.ones((2, 5))
print("2次元:", ones_2d.shape)      # (2, 5)

# 異なるサイズの配列
ones_rect = np.ones((4, 3))
print("長方形配列:\n", ones_rect)

2-2. データ型とスケーリング

# 整数型での1配列
int_ones = np.ones(5, dtype=int)
print("整数1配列:", int_ones)       # [1 1 1 1 1]

# 1配列をスケーリング
scaled_ones = np.ones(5) * 10
print("10倍:", scaled_ones)         # [10. 10. 10. 10. 10.]

# 異なる値への変換
negative_ones = -np.ones(4)
print("負の1:", negative_ones)      # [-1. -1. -1. -1.]

2-3. 単位行列の生成

# eye()を使った単位行列
identity = np.eye(4)
print("単位行列:\n", identity)

# ones()とdiag()での単位行列作成
manual_identity = np.zeros((4, 4))
manual_identity[np.diag_indices(4)] = 1
print("手動単位行列 対角:", np.diag(manual_identity))

3. numpy.full() – 任意値初期化配列

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

# 任意の値で初期化
full_99 = np.full(5, 99)
print("99初期化:", full_99)         # [99 99 99 99 99]

# 2次元配列
full_2d = np.full((3, 4), 7.5)
print("7.5初期化 形状:", full_2d.shape)

# 負の値での初期化
full_negative = np.full(4, -3.14)
print("負の値:", full_negative)     # [-3.14 -3.14 -3.14 -3.14]

3-2. 様々なデータ型での初期化

# 文字列での初期化
str_full = np.full(3, 'Hello', dtype='U10')
print("文字列配列:", str_full)      # ['Hello' 'Hello' 'Hello']

# 真偽値での初期化
bool_full = np.full(5, True, dtype=bool)
print("True配列:", bool_full)       # [ True  True  True  True  True]

# 複素数での初期化
complex_full = np.full(3, 2+3j, dtype=complex)
print("複素数配列:", complex_full)  # [2.+3.j 2.+3.j 2.+3.j]

3-3. 配列や特殊値での初期化

# NaN初期化(欠損値)
nan_array = np.full(5, np.nan)
print("NaN配列:", nan_array)        # [nan nan nan nan nan]

# 無限大初期化
inf_array = np.full(3, np.inf)
print("無限大配列:", inf_array)     # [inf inf inf]

# 計算結果での初期化
calc_value = np.pi / 4
pi_array = np.full(4, calc_value)
print("π/4配列:", pi_array)

4. like系関数 – 既存配列ベースの初期化

4-1. zeros_like, ones_like, full_like

# 元となる配列
original = np.array([[1, 2, 3], [4, 5, 6]])
print("元配列形状:", original.shape)
print("元配列データ型:", original.dtype)

# 同じ形状でゼロ初期化
zeros_like = np.zeros_like(original)
print("zeros_like形状:", zeros_like.shape)

# 同じ形状で1初期化
ones_like = np.ones_like(original)
print("ones_like:\n", ones_like)

# 同じ形状で任意値初期化
full_like = np.full_like(original, 42)
print("full_like:\n", full_like)

4-2. データ型の変更

# 元配列とは異なるデータ型
int_original = np.array([1, 2, 3], dtype=int)

# 浮動小数点型で初期化
float_zeros = np.zeros_like(int_original, dtype=float)
print("元配列型:", int_original.dtype)    # int64
print("新配列型:", float_zeros.dtype)     # float64

# 複素数型で初期化
complex_ones = np.ones_like(int_original, dtype=complex)
print("複素数型:", complex_ones)          # [1.+0.j 1.+0.j 1.+0.j]

5. fill()メソッド – 既存配列の値変更

5-1. 基本的なfill操作

# 既存配列の全要素を変更
arr = np.array([1, 2, 3, 4, 5])
print("変更前:", arr)               # [1 2 3 4 5]

arr.fill(0)
print("fill(0)後:", arr)           # [0 0 0 0 0]

# 異なる値でfill
arr.fill(99)
print("fill(99)後:", arr)          # [99 99 99 99 99]

5-2. 多次元配列でのfill

# 2次元配列のfill
matrix = np.ones((3, 4))
print("fill前:\n", matrix)

matrix.fill(7)
print("fill(7)後:\n", matrix)

# 部分的なfill(スライス利用)
matrix[0, :].fill(1)               # 最初の行のみ1で埋める
matrix[:, -1].fill(9)              # 最後の列のみ9で埋める
print("部分fill後:\n", matrix)

5-3. データ型制約とfill

# データ型による制約
int_arr = np.zeros(5, dtype=int)
int_arr.fill(3.14)                 # 自動的に整数に変換
print("整数配列fill(3.14):", int_arr)  # [3 3 3 3 3]

# 複素数配列のfill
complex_arr = np.zeros(3, dtype=complex)
complex_arr.fill(1+2j)
print("複素数fill:", complex_arr)   # [1.+2.j 1.+2.j 1.+2.j]

6. 実践的な使用例

6-1. 初期化配列を使った計算処理

def gaussian_kernel(size, sigma=1.0):
    """ガウシアンカーネルの生成"""
    # 座標系の作成
    coords = np.arange(size) - size // 2
    
    # ガウシアン関数の計算用に1で初期化
    kernel = np.ones(size)
    
    # ガウシアン関数を適用
    for i, x in enumerate(coords):
        kernel[i] = np.exp(-(x**2) / (2 * sigma**2))
    
    # 正規化
    return kernel / kernel.sum()

# 1次元ガウシアンカーネル
gauss_1d = gaussian_kernel(7, sigma=1.5)
print("ガウシアンカーネル:", gauss_1d)

6-2. マスク配列の作成

def create_circular_mask(height, width, center=None, radius=None):
    """円形マスクの作成"""
    if center is None:
        center = (width // 2, height // 2)
    if radius is None:
        radius = min(center[0], center[1], width - center[0], height - center[1])
    
    # False(0)で初期化
    mask = np.zeros((height, width), dtype=bool)
    
    # 各点との距離を計算
    y, x = np.ogrid[:height, :width]
    dist_from_center = np.sqrt((x - center[0])**2 + (y - center[1])**2)
    
    # 円内の点をTrueに設定
    mask[dist_from_center <= radius] = True
    
    return mask

# 円形マスクの生成
circular_mask = create_circular_mask(10, 10)
print("円形マスク:")
print(circular_mask.astype(int))  # 表示用に整数変換

6-3. 初期値設定付きの数値シミュレーション

def heat_diffusion_1d(length, time_steps, initial_temp=0, boundary_temp=100):
    """1次元熱拡散シミュレーション"""
    # 初期温度で配列を初期化
    temperature = np.full(length, initial_temp, dtype=float)
    
    # 境界条件
    temperature[0] = boundary_temp
    temperature[-1] = boundary_temp
    
    # 時間発展
    alpha = 0.01  # 熱拡散係数
    dt = 0.1
    dx = 1.0
    
    temp_history = [temperature.copy()]
    
    for t in range(time_steps):
        new_temp = temperature.copy()
        
        # 内部点の更新(有限差分法)
        for i in range(1, length-1):
            new_temp[i] = temperature[i] + alpha * dt / (dx**2) * \
                         (temperature[i+1] - 2*temperature[i] + temperature[i-1])
        
        temperature = new_temp
        temp_history.append(temperature.copy())
    
    return np.array(temp_history)

# 熱拡散シミュレーション
heat_sim = heat_diffusion_1d(10, 5)
print("初期状態:", heat_sim[0])
print("最終状態:", heat_sim[-1])

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

7-1. 初期化方法の速度比較

import time

def benchmark_initialization(size, iterations=1000):
    """初期化方法のベンチマーク"""
    
    # zeros()
    start = time.time()
    for _ in range(iterations):
        arr = np.zeros(size)
    zeros_time = time.time() - start
    
    # ones()
    start = time.time()
    for _ in range(iterations):
        arr = np.ones(size)
    ones_time = time.time() - start
    
    # full()
    start = time.time()
    for _ in range(iterations):
        arr = np.full(size, 42)
    full_time = time.time() - start
    
    # empty() + fill()
    start = time.time()
    for _ in range(iterations):
        arr = np.empty(size)
        arr.fill(42)
    empty_fill_time = time.time() - start
    
    return zeros_time, ones_time, full_time, empty_fill_time

# ベンチマーク実行
size = 100000
z_time, o_time, f_time, ef_time = benchmark_initialization(size)

print(f"配列サイズ: {size:,}")
print(f"zeros():      {z_time:.6f}秒")
print(f"ones():       {o_time:.6f}秒")
print(f"full():       {f_time:.6f}秒")
print(f"empty+fill(): {ef_time:.6f}秒")

7-2. メモリ効率的な大規模配列初期化

def efficient_large_array_init(shape, value, chunk_size=1000000):
    """メモリ効率的な大規模配列初期化"""
    total_size = np.prod(shape)
    
    if total_size <= chunk_size:
        # 小さい配列は通常の方法
        return np.full(shape, value)
    
    # 大規模配列はチャンク処理
    arr = np.empty(shape)
    flat_arr = arr.flat
    
    processed = 0
    while processed < total_size:
        current_chunk = min(chunk_size, total_size - processed)
        flat_arr[processed:processed + current_chunk] = value
        processed += current_chunk
        
        print(f"進捗: {processed:,} / {total_size:,}")
    
    return arr

# 使用例(小さいサイズでデモ)
large_array = efficient_large_array_init((1000, 1000), 3.14, chunk_size=200000)
print(f"大規模配列作成完了: {large_array.shape}")
print(f"値の確認: {large_array[0, 0]}, {large_array[500, 500]}")

8. 特殊な初期化パターン

8-1. 勾配パターンの初期化

def create_gradient_array(shape, start_value, end_value, axis=0):
    """勾配パターンの配列作成"""
    arr = np.zeros(shape)
    
    if len(shape) == 1:
        # 1次元の場合
        n = shape[0]
        for i in range(n):
            arr[i] = start_value + (end_value - start_value) * i / (n - 1)
    elif len(shape) == 2:
        # 2次元の場合
        if axis == 0:  # 行方向の勾配
            for i in range(shape[0]):
                value = start_value + (end_value - start_value) * i / (shape[0] - 1)
                arr[i, :] = value
        else:  # 列方向の勾配
            for j in range(shape[1]):
                value = start_value + (end_value - start_value) * j / (shape[1] - 1)
                arr[:, j] = value
    
    return arr

# 勾配配列の生成
gradient_1d = create_gradient_array(10, 0, 1)
print("1次元勾配:", gradient_1d)

gradient_2d = create_gradient_array((5, 5), 0, 10, axis=1)
print("2次元勾配(列方向):")
print(gradient_2d)

8-2. チェッカーボードパターン

def create_checkerboard(height, width, value1=0, value2=1):
    """チェッカーボードパターンの作成"""
    # 初期値でfull初期化
    board = np.full((height, width), value1)
    
    # チェッカーパターンを作成
    for i in range(height):
        for j in range(width):
            if (i + j) % 2 == 1:
                board[i, j] = value2
    
    return board

# チェッカーボードの生成
checkerboard = create_checkerboard(8, 8, 0, 1)
print("チェッカーボード:")
print(checkerboard)

8-3. ランダムシード付き固定初期化

def create_reproducible_random_like(template_array, seed=42, scale=1.0):
    """再現可能なランダム様初期化"""
    # シード固定
    np.random.seed(seed)
    
    # テンプレートと同じ形状で0初期化
    arr = np.zeros_like(template_array, dtype=float)
    
    # 固定パターンで擬似ランダム値を生成
    flat_arr = arr.flat
    for i in range(arr.size):
        # 線形合同法的な擬似ランダム
        value = ((i * 1664525 + 1013904223) % (2**32)) / (2**32) * scale
        flat_arr[i] = value
    
    return arr

# 使用例
template = np.array([[1, 2], [3, 4]])
pseudo_random = create_reproducible_random_like(template, seed=42, scale=10)
print("擬似ランダム初期化:")
print(pseudo_random)

9. よくあるエラーと対処法

9-1. データ型の自動変換問題

def handle_dtype_issues():
    """データ型関連の問題と対処"""
    
    # 問題1: 整数配列に浮動小数点値
    int_arr = np.zeros(5, dtype=int)
    int_arr.fill(3.14)  # 3に切り捨てられる
    print("整数配列fill(3.14):", int_arr)  # [3 3 3 3 3]
    
    # 解決: 適切なデータ型を選択
    float_arr = np.zeros(5, dtype=float)
    float_arr.fill(3.14)
    print("浮動小数点配列:", float_arr)    # [3.14 3.14 3.14 3.14 3.14]
    
    # 問題2: オーバーフロー
    small_int = np.zeros(3, dtype=np.int8)  # -128 to 127
    small_int.fill(200)  # オーバーフロー
    print("オーバーフロー結果:", small_int)
    
    # 解決: 値の範囲チェック
    safe_value = min(200, 127)  # データ型の上限以下に制限
    small_int.fill(safe_value)
    print("安全な値:", small_int)

handle_dtype_issues()

9-2. メモリ不足エラーの対処

def safe_large_array_creation(shape, value):
    """安全な大規模配列作成"""
    import psutil
    import os
    
    # 必要メモリ量の推定
    element_size = np.dtype(float).itemsize  # 8 bytes for float64
    required_memory = np.prod(shape) * element_size
    
    # 利用可能メモリの確認
    available_memory = psutil.virtual_memory().available
    
    print(f"必要メモリ: {required_memory:,} bytes")
    print(f"利用可能メモリ: {available_memory:,} bytes")
    
    if required_memory > available_memory * 0.8:  # 80%以上使用は危険
        print("警告: メモリ不足の可能性があります")
        return None
    
    try:
        arr = np.full(shape, value)
        print("配列作成成功")
        return arr
    except MemoryError:
        print("エラー: メモリ不足で配列を作成できませんでした")
        return None

# 使用例
result = safe_large_array_creation((10000, 10000), 1.0)
if result is not None:
    print(f"作成された配列形状: {result.shape}")

9-3. 次元エラーの回避

def safe_array_initialization(shape_input, value):
    """安全な配列初期化(エラーハンドリング付き)"""
    try:
        # 形状の正規化
        if isinstance(shape_input, int):
            shape = (shape_input,)
        else:
            shape = tuple(shape_input)
        
        # 負の値チェック
        if any(dim <= 0 for dim in shape):
            raise ValueError("配列の次元は正の整数である必要があります")
        
        # 配列作成
        arr = np.full(shape, value)
        
        print(f"配列作成成功: 形状{shape}, 値{value}")
        return arr
        
    except (TypeError, ValueError) as e:
        print(f"エラー: {e}")
        return None

# テスト
good_array = safe_array_initialization([3, 4], 42)
bad_array = safe_array_initialization([-1, 4], 42)  # エラーケース

まとめ

NumPyで全要素を同じ値で初期化する方法をマスターすることで、効率的なデータ処理が可能になります。

主要なポイント:

  • np.zeros(): 0初期化、最も高速
  • np.ones(): 1初期化、単位行列などに便利
  • np.full(): 任意値初期化、最も柔軟
  • array.fill(): 既存配列の値変更、メモリ効率的
  • like系関数: 既存配列と同じ形状で初期化

適切な関数を選択して、パフォーマンスと可読性を両立したNumPyプログラムを作成しましょう!

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

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

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

■テックジム東京本校

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

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

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

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