閉じる

NumPyのnp.fullで定数配列を効率的に作成する方法:使い方からdtypeの注意点まで解説

Pythonを用いたデータ分析や数値計算において、特定の数値で埋め尽くされた配列を準備するシーンは非常に多く存在します。

例えば、初期値として全ての要素を「-1」に設定したり、特定のフラグ値で配列を初期化したりする場合です。

このようなタスクを直感的かつ効率的に実行するための関数が、NumPyライブラリのnp.fullです。

np.fullは、指定した形状(shape)と値(fill_value)に基づいて、すべての要素が同じ値を持つ配列を生成します。本記事では、この関数の基本的な使い方から、実務でハマりやすいデータ型(dtype)の注意点、さらには他の配列生成関数とのパフォーマンスの違いまで、プロの視点で詳しく解説します。

NumPyのnp.fullとは:定数配列を生成する基本

NumPyには配列を生成するための便利な関数が多数用意されていますが、その中でも「任意の定数で埋められた配列」を生成することに特化しているのがnp.fullです。

以前のPythonコードでは、np.onesで作成した配列に数値を掛け算する手法も使われていましたが、np.fullを使用する方がコードの意図が明確になり、可読性が向上します。

また、内部的な処理としても、特定の値を直接メモリに書き込むため効率的です。

基本的な構文と引数の解説

まずは、np.fullの基本的な構文を確認しましょう。

Python
import numpy as np

# 基本構文
# np.full(shape, fill_value, dtype=None, order='C', *, like=None)

主要な引数の役割は以下の通りです。

引数名概要
shape配列の形状を指定します。整数(1次元)または整数のタプル(多次元)で指定します。
fill_value配列を埋めるための定数値を指定します。
dtype配列のデータ型を指定します。省略した場合は fill_value から推論されます。
orderメモリ上の配置順序を指定します(’C’は行優先、’F’は列優先)。通常はデフォルトのままで問題ありません。

特に重要なのは、shapeとfill_valueの2点です。これらを正しく組み合わせることで、目的に応じた多次元配列を瞬時に作成できます。

np.fullの具体的な使い方

ここからは、コード例を交えて具体的な使い道を見ていきましょう。

1次元配列から多次元配列、そして既存の配列の形状を模倣する方法まで紹介します。

1次元配列と多次元配列の生成

もっともシンプルな例として、5つの要素をすべて「7」で埋めた1次元配列を作成します。

Python
import numpy as np

# 要素数5、値が7の1次元配列
arr_1d = np.full(5, 7)

print(arr_1d)
実行結果
[7 7 7 7 7]

次に、2行3列の行列(2次元配列)を「0.5」で埋める例です。

Python
import numpy as np

# 2行3列、値が0.5の2次元配列
arr_2d = np.full((2, 3), 0.5)

print(arr_2d)
実行結果
[[0.5 0.5 0.5]
 [0.5 0.5 0.5]]

このように、shapeにタプルを渡すだけで、任意の次元の定数配列を簡単に作成できるのがnp.fullの強みです。

既存の配列をベースにするnp.full_like

「すでにある配列と同じ形状、同じデータ型で、別の値で埋めたい」という場合には、np.full_likeが便利です。

Python
import numpy as np

base_array = np.array([[1, 2], [3, 4]])

# base_arrayと同じ形状で、すべての値を-1にする
new_array = np.full_like(base_array, -1)

print(new_array)
実行結果
[[-1 -1]
 [-1 -1]]

np.full_likeを使うことで、元の配列のshapedtypeをわざわざ取得して再指定する手間が省け、コードがスッキリします。

dtype(データ型)の指定と注意点

np.fullを使用する際に最も注意すべきなのが、「データ型の推論」です。

NumPyは、提供された fill_value から最適なデータ型を自動的に決定しようとしますが、これが予期せぬ挙動を招くことがあります。

自動推論の挙動と明示的な指定の重要性

例えば、整数を渡せば int 型になり、浮動小数点数を渡せば float 型になります。

Python
import numpy as np

a = np.full(3, 10)     # int64 (環境依存)
b = np.full(3, 10.0)   # float64

print(f"a dtype: {a.dtype}")
print(f"b dtype: {b.dtype}")
実行結果
a dtype: int64
b dtype: float64

ここで問題になるのは、後から配列の要素を書き換える場合です。

もし整数型で初期化された配列に、後から小数を入れると、小数点以下が切り捨てられてしまいます。

Python
import numpy as np

arr = np.full(3, 1) # int型で生成
arr[0] = 1.9        # floatを代入しようとする

print(arr)
実行結果
[1 1 1]

上記の結果のように、1.9を代入したつもりが「1」になってしまいます。

これを防ぐためには、生成時に明示的に dtype を指定することが推奨されます。

Python
# 明示的にfloat型を指定
arr = np.full(3, 1, dtype=np.float64)
arr[0] = 1.9

print(arr)
実行結果
[1.9 1.  1. ]

浮動小数点数(NaN)で埋める際の注意

欠損値を表す np.nan で配列を埋めたい場合、np.nan 自体が浮動小数点数型であるため、自動的に float 型の配列が作成されます。

しかし、整数型の配列に NaN を入れることはできないため、混合して扱う可能性がある場合は最初から dtype=float を意識しましょう。

他の配列生成関数との比較

NumPyには他にも配列を生成する関数があります。

np.full と何が違うのか、どのように使い分けるべきかを整理します。

zeros、ones、emptyとの違いと使い分け

  1. np.zeros: すべての要素を「0」で初期化します。0で埋めることが確定しているなら、np.full(shape, 0) よりも高速で直感的です。
  2. np.ones: すべての要素を「1」で初期化します。
  3. np.empty: メモリ領域を確保するだけで、中身を初期化しません。そのため非常に高速ですが、中身には「以前使われていたメモリのゴミデータ」が入っています。生成直後にすべての要素を上書きする場合にのみ推奨されます。

以下の表に使い分けをまとめました。

関数適した用途速度
np.zeros0で初期化する場合高速
np.ones1で初期化する場合高速
np.full0, 1以外の特定の数値で初期化する場合標準
np.empty即座に全要素を別データで埋める場合最速

実務において、例えば「全ての要素を100で埋める」場合に np.ones(shape) * 100 と書く人がいますが、これは「1で埋める処理」と「100を掛ける処理」の2段階が発生するため、np.full(shape, 100) と書く方がパフォーマンスとコードの明快さの両面で優れています。

応用編:実践的な活用シーン

np.full は単なる初期化以外にも、多くの場面で応用されています。

初期値としての利用とマスク処理

アルゴリズムの実装において、最短距離を求めるダイクストラ法などのグラフ理論では、各ノードへの距離を最初に「無限大(infinity)」で初期化することがよくあります。

このような場合、np.inf を使って次のように作成します。

Python
import numpy as np

# 無限大で初期化されたコスト行列
costs = np.full((5, 5), np.inf)

print(costs)
実行結果
[[inf inf inf inf inf]

[inf inf inf inf inf]

[inf inf inf inf inf]

[inf inf inf inf inf]

[inf inf inf inf inf]]

また、画像処理や機械学習のデータ前処理において、特定の値を背景色やパディング値として利用する際にも np.full は重宝されます。

実行速度とメモリ効率

大量のデータを扱う際、np.full の実行速度が気になるかもしれません。

NumPyはC言語で実装されているため、Pythonのループでリストを作成するよりも圧倒的に高速です。

ただし、非常に巨大な配列を生成する場合、メモリ消費量に注意が必要です。

dtype=np.int64(8バイト)で 1,000,000 要素の配列を作ると、それだけで約8MBのメモリを消費します。

用途に応じて int32float32 を選択することで、メモリ使用量を半分に抑えることが可能です。

まとめ

NumPyの np.full は、任意の定数で埋められた配列を効率的に作成するための強力なツールです。

本記事のポイントを振り返ります。

  • np.fullは、指定した形状と値で配列を即座に生成する。
  • np.ones() * value よりも可読性が高く、効率的である。
  • dtypeを明示的に指定しないと、意図しない型変換(切り捨て)が発生する恐れがある。
  • 既存の配列の形状をコピーしたい場合は np.full_like が便利である。
  • 0や1で埋める場合は np.zerosnp.ones を選ぶのが定石。

データサイエンスや科学計算の現場では、正確な数値管理が求められます。

配列生成の第一歩として np.full を正しく使いこなし、堅牢でクリーンなPythonコードを目指しましょう。

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

URLをコピーしました!