メインコンテンツへスキップ

NumPyのemptyで空(長さ0)の配列を作る

·1419 文字·3 分
目次

はじめに
#

NumPyのempty関数を用いて、np.empty(0), np.empty([0, 0]), …とすることで、空の(要素を持たない)任意の次元の配列を作成できる。本記事では、空の配列の作り方、使い方について簡単に考察する。

環境
#

  • NumPy 1.19

本記事では、以下の通りライブラリをインポートしていることを前提とする。

import numpy as np

np.emptyについて
#

np.emptyは中身を初期化せずに配列を作成する関数である。主な引数は次の通り。

np.empty(shape, dtype=float)

shapeは配列の形状を決める引数であり、

  • int
  • intを格納するタプル
  • intを格納するリスト

のいずれかをとる。

dtypeは配列の数値の型を決める引数であり、

  • int
  • float
  • np.float32
  • np.int8

などを指定する(デフォルトはfloat)。

要素数が5つの1次元配列を生成するには、shape5、または(5)、または[5]とする。ただし、配列の中身は変わる場合がある。

>>> np.empty(5)
array([0.  , 0.25, 0.5 , 0.75, 1.  ])
>>> np.empty((5))
array([0.  , 0.25, 0.5 , 0.75, 1.  ])
>>> np.empty([5])
array([0.  , 0.25, 0.5 , 0.75, 1.  ])

要素数が2×3の2次元配列を生成するには、shape(2, 3)、または[2, 3]とする。

>>> np.empty((2, 3))
array([[0.93137112, 0.92761264, 0.98531337],
       [0.28813119, 0.49620105, 0.41308828]])
>>> np.empty([2, 3])
array([[0.93137112, 0.92761264, 0.98531337],
       [0.28813119, 0.49620105, 0.41308828]])

np.empty()は、中身が全て0の配列を生成するnp.zeros()や、中身が全て1の配列を生成するnp.ones()と比較すると、配列を高速に生成できる利点がある。

空の配列の生成
#

冒頭に記したように、np.empty()shape0[0, 0], …とすると、任意の次元の空の配列を生成できる。

1次元配列の場合

>>> a1 = np.empty(0)
>>> a1
array([], dtype=float64)
>>> a1.ndim # 次元数
1

2次元配列の場合

>>> a2 = np.empty([0, 0])
>>> a2
array([], shape=(0, 0), dtype=float64)
>>> a2.ndim # 次元数
2

同様に、

  • np.empty([0, 0, 0])で3次元の空の配列
  • np.empty([0, 0, 0, 0])で4次元の空の配列

がそれぞれ生成できる。

なお、np.zeros()関数やnp.ones()関数を使って、

  • np.zeros(0)
  • np.ones([0, 0])

としても、同様に空の配列を作成できる。しかし、関数名と異なり要素に0や1を含まない配列が生成されて紛らわしいため、np.empty()関数を使うべきだと個人的に思う。

空の配列の使い方
#

空の配列は、「配列を結合したいが、最終的に得られる配列のサイズが分からない場合」、あるいは「計算の規模が小さく、かつプログラムの可読性を重視したい場合」に用いるべきである。

配列を逐次的に結合すると、その都度メモリを確保する必要があるため、実行速度が低下する。 そのため、最終的な配列のサイズが分かっている場合には、初めに必要なサイズの配列を確保して、逐次的に配列を代入した方が速く実行できる。

比較のため、配列を結合する関数stack()と、最初に配列を確保する関数substitute()を作成した。両者とも、長さが1000で要素が全て1の配列を返す。関数stack()では長さ1の配列を1000回結合し、関数substitute()では最初に確保した配列に長さ1の配列を1000回代入している。

def stack():
    a = np.empty(0)
    for i in range(1000):
        a = np.hstack([a, np.array(1)])
    return a
        
def substitute():
    a = np.empty(1000)
    for i in range(1000):
        a[i] = np.array(1)
    return a

IPythonの%timeitマジックコマンドで実行速度を測定する。

>>> %timeit stack()
5.93 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit substitute()
436 µs ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

stack()関数とsubstitute()関数の平均実行時間はそれぞれ5.93ミリ秒と0.436ミリ秒であり、substitute()の方が約14倍高速である。すなわち、処理速度を重視する場合、最初に配列を確保した方が良い。

参考
#

numpy.empty — NumPy v1.19 Manual

Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

NumPyを使った高速フーリエ変換による周波数解析
·1276 文字·3 分
NumPyのfftパッケージを使って、FFT (Fast Fourier Transform, 高速フーリエ変換) による離散信号の周波数解析を行い、信号の振幅を求める。
NumPyで使える統計の関数
·673 文字·2 分
NumPyで利用できる統計の関数について。
NumPyで使える数学の関数
·1031 文字·3 分
NumPyで利用できる数学の関数について。
NumPy配列の演算
·1222 文字·3 分
NumPy配列の四則演算と線形代数学の演算について。
NumPy配列の操作
·1325 文字·3 分
NumPy配列のコピーや次元の結合、結合・分割、ソートについて。
NumPy配列の確認
·975 文字·2 分
作成したNumPy配列の要素などを確認する。