Numpy は最も人気のある数学計算の Python ライブラリです。
多次元配列や行列、数学関数、数値ジェネレータなど、これらに限定されない多くの数学的ツールを提供します。
NumPyの基本的なツールの1つは ndarray
– N次元配列です。
今日は、NumPy.arange()
関数を使って、ある範囲で生成されたndarrayを作成します。
パラメータとリターン
numpy.arange([start, ]stop, [step, ]dtype=None)
指定された区間内の等間隔な値を返します。
- start は,配列の始点となる数値(整数または実数)です。これはオプションです。
- stop は、配列の終点となる数値(整数または実数)であり、配列には含まれません。
- step は、配列内の連続した値の間隔を指定する数値です。オプションで、デフォルトでは1です。
- dtype は、配列の要素の出力タイプです。デフォルトは None です。
このメソッドは、等間隔に並んだ値の ndarray
を返します。
np.arange()の例
NumPyのインポート
NumPyを使い始めるには、外部ライブラリであるNumPyをインポートする必要があります。
import NumPy as np
インストールされていない場合は、pip
で簡単にインストールすることができます。
$ pip install numpy
すべての引数 np.arange()
arange()`が関数のすべての引数でどのように動作するかを見てみましょう。
例えば、0から始まり、10で止まる、ステップサイズ3の整数を生成するシーケンスが欲しいとします。
Python環境、またはREPLで、シーケンスを範囲指定で生成してみましょう。
>>> result_array = np.arange(start=0, stop=10, step=2, dtype=int)
arrayは生成された要素を含む
ndarray` です。
>>> result_array
array([0, 2, 4, 6, 8])
注目すべきは、 stop
要素は含まれず、 start
要素は含まれることです。
したがって、シーケンスの次の要素が 10
であるべきにもかかわらず、 0
はありますが 10
はありません。
注意: いつものように、位置引数や名前付き引数を指定することなく、位置引数を指定することができます。
位置を暗記するまでは、名前を付けておくと便利かもしれません。
array = np.arange(start=0, stop=10, step=2, dtype=int)
# These two statements are the same
array = np.arange(0, 10, 2, int)
また、これらの引数の位置は、 start
, stop
, step
, dtype
という順序に従わなければなりません。
np.arange() with stop
引数を1つだけ指定した場合、それが stop
値として扱われます。
デフォルトのステップは 1
、start
は 0
で、 stop
値までのすべての数値が出力されます。
>>> result_array = np.arange(5)
>>> result_array
array([0, 1, 2, 3, 4])
np.arange() with start and stop
2つの引数を指定すると、デフォルトで start
と stop
になり、デフォルトの step
は 1
になります – つまり、ステップサイズを考えずに簡単に特定の範囲を作成することができます。
>>> result_array = np.arange(5, 10)
>>> result_array
array([5, 6, 7, 8, 9])
前の例と同様に、ここでは整数の代わりに浮動小数点数を使用することもできます。
例えば、5.5から始めることができます。
>>> result_array = np.arange(5.5, 11.75)
結果として、以下のような配列になります。
>>> result_array
array([ 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5])
np.arange() with start, stop and step
デフォルトの dtype
は None
で、この場合は int
が使用されます。
したがって、 start
, stop
, step
を指定して、整数ベースの範囲を簡単に作成することができます。
例えば、 6
(包含) から 22
(排他) までのすべての偶数列を生成してみよう。
>>> result_array = np.arange(6, 22, 2)
結果は、6 から 22 を除くすべての偶数になります。
>>> result_array
array([ 6, 8, 10, 12, 14, 16, 18, 20])
np.arange()による逆順の範囲指定
np.arange()` 関数に負のパラメータを渡すことで、数値の逆配列を得ることもできます。
startはカウントを開始する大きい方の数字、
stop` は小さい方の数字、step は負の数です。
result_array = np.arange(start=30,stop=14, step=-3)
結果は、負の数である 3 のステップを持つ降順の数値の配列となります。
>>> result_array
array([30, 27, 24, 21, 18, 15])
np.arange() による空の NDArray の作成
次のようにして、空のarangeを作成することもできます。
>>> result_array = np.arange(0)
結果は空の配列になります。
>>> result_array
array([], dtype=int32)
これは、 0
が設定した stop
の値で、スタート値もデフォルトで 0
なので、カウントが始まる前に止まってしまうからです。
つまり、カウントは開始する前に停止します。
結果が空の配列になるもう一つのケースは、ステップが正で、開始値が停止値より大きい場合です。
>>> result_array = np.arange(start=30, stop=10, step=1)
この場合も結果は空の配列になります。
>>> result_array
array([], dtype=int32)
これは逆の場合も起こりえます。
小さな数から始めて、大きな数で止め、step
を負の数にすることができます。
出力も空の配列になります。
>>> result_array = np.arange(start=10, stop=30, step=-1)
これも空の ndarray
になります。
>>> result_array
array([], dtype=int32)
np.arange()でサポートされているデータ型
>
> 引数 dtype
のデフォルトは int
で、NumPy の有効なデータ型であればどれでも構いません。
注:これは、標準的なPythonのデータ型と混同しないようにしましょう。
より一般的なデータ型には短縮版を使うことができますし、完全なデータ型には np.
というプレフィックスをつけることができます。
np.arange(..., dtype=int)
np.arange(..., dtype=np.int32)
np.arange(..., dtype=np.int64)
その他のデータ型、例えば np.csignle
のようなデータ型では、型の前に np.
を付けます。
>>> result_array = np.arange(start=10, stop=30, step=1, dtype=np.csingle)
>>> result_array
array([10.+0.j, 11.+0.j, 12.+0.j, 13.+0.j, 14.+0.j, 15.+0.j, 16.+0.j,
17.+0.j, 18.+0.j, 19.+0.j, 20.+0.j, 21.+0.j, 22.+0.j, 23.+0.j,
24.+0.j, 25.+0.j, 26.+0.j, 27.+0.j, 28.+0.j, 29.+0.j],
dtype=complex64)
一般的な短縮形のデータ型は float
です。
>>> result_array = np.arange(start=10, stop=30, step=1, dtype=float)
>>> result_array
array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.,
23., 24., 25., 26., 27., 28., 29.])
>
サポートされているNumPyのデータ型の一覧は、公式ドキュメントを参照してください。
np.arange() vs np.linspace()
np.linspace()は、等間隔の配列を返すという点では
np.arange()` と同じです。
しかし、いくつかの違いがあります。
np.linspace()では、ステップを指定する代わりに、ある範囲に含まれるサンプルの数を指定します。
さらに、返される配列に終点を含めることができます。
もう一つの違いは、np.linspace()`は1つの配列だけを返すのではなく、複数の配列を生成することができる点です。
これは、終点を含む5つのサンプルと np.linspace()
の簡単な例です。
>>> result_array = np.linspace(0, 20, num=5, endpoint=True)
>>> result_array
array([ 0., 5., 10., 15., 20.])
ここでは、サンプル数とステップサイズの両方が 5
ですが、これは偶然です。
>>> result_array = np.linspace(0, 20, num=2, endpoint=True)
>>> result_array
array([ 0., 20.])
ここでは、0と20の間に2点作っているので、当然20ステップ離れています。
また、endpoint
をFalse
にすると、np.linspace()は最後の要素を含まないという意味で、より
np.arange()`に近い振る舞いをするようになります。
>>> result_array = np.linspace(0, 20, num=5, endpoint=False)
>>> result_array
array([ 0., 4., 8., 12., 16.])
np.arange() vs 組み込みの range()
Pythonの組み込み関数である range()
と np.arange()
は多くの類似点を持ちますが、若干の相違点もあります。
以下の節では、両者の類似点と相違点をいくつか紹介します。
パラメータとリターン
主な共通点は、どちらも start
, stop
, step
を持つことである。
さらに、どちらも start
を含み、 stop
を含まない。
また、デフォルトの step
は 1
である。
しかし
-
np.arange()
-
浮動小数点数、複素数を含む複数のデータ型を扱うことができる。
-
ndarray
を返します。 -
配列は完全にメモリ内に作成されます。
-
range()
-
整数のみを扱うことができる
- range` オブジェクトを返します。
- オンデマンドで数値を生成する
効率とスピード
np.arange()と組み込みの
range()` 関数の間には、速度と効率の面でいくつかの違いがあります。
range関数はオンデマンドで数値を生成し、インメモリで前もって作成することはありません。
これは、その範囲のどこかで壊れることが分かっている場合に、処理を高速化するのに役立ちます。
for i in range(100000000):
if i == some_number:
break
これは、すべての数値を前もって作成するわけではないので、より少ないメモリを消費することになります。
これは、 ndarrays
を最初に構築する際の速度を遅くすることにもなります。
しかし、まだメモリ上に全範囲の数値が必要な場合は、 np.arange()
の方が range()
よりもかなり高速に構築できます。
例えば、単に反復処理を行うだけであれば、配列を作成する時間がかかるため、初期コストが高くなり np.arange()
のパフォーマンスは低下します。
$ python -m timeit "for i in range(100000): pass"
200 loops, best of 5: 1.13 msec per loop
$ python -m timeit "import numpy as np" "for i in np.arange(100000): pass"
100 loops, best of 5: 3.83 msec per loop