📘

NumPy入門(配列基礎)

2024/03/23に公開

なんか、ソフトウェアエンジニアってかっこいいですよね。DjangoやAmon2でのWebアプリ開発もできるにはできますが本職はインフラエンジニアなので、ソフトウェアエンジニアに対する憧れがあります。
ソフトウェアエンジニアリングを学びたいならば最近はきっとデータサイエンスを学習しておくと一石二鳥な予感がするので、少ないお小遣いで Pythonデータサイエンスハンドブック(第二版) を買ってみました。

学んだことを少しずつアウトプットしてみます。知ったことを試してみた結果の一部なので、網羅的に知りたい際は書籍や公式docをご参照ください。

Pythonにおけるデータサイエンスの基盤はNumPy(ナムパイ)であるらしく、NumPyをよく理解する必要があるそうです。

有名なpandasもNumPyの上に作成されたライブラリです。

以下実行結果はは基本的に ipythonコマンドで起動したコンソールにて実行した結果です。

NumPy配列

NumPy配列というのはPythonの配列を拡張したようなもので、Pythonの配列というのはCPythonの場合はPythonの変数一つを表すCの構造体へのポインタのリストになっていて、メモリ上のオーバーヘッドが大きいらしいです。これはPythonが動的型付け言語であるため。

NumPy配列は型が配列内で一つに固定化されることと引き換えに、より効率よく大量データを扱えるようになっています。

※Pythonも3.3以降ならば、arrayを利用して型を共通にした配列を作れます

In [1]: import array

In [2]: list = list((1,2,3,4,5))

In [3]: a = array.array('i', list)

In [4]: a
Out[4]: array('i', [1, 2, 3, 4, 5])

'i'は整数を意味する型コードらしい。

Numpy配列の作成

np.arrayでPythonのリストからNumPy配列を作る

In [1]: import numpy as np

In [2]: np.array([1,2,3,4,5])
Out[2]: array([1, 2, 3, 4, 5])

NumPy配列は全部同じ型になる制約があって、例えば文字列を混ぜると全部文字列になりました。

In [3]: np.array([1,2,3,4,5,"string"])
Out[3]: array(['1', '2', '3', '4', '5', 'string'], dtype='<U21')

多次元配列も作成できる(Pythonでも作れるが実は1次元のデータ列)

In [4]: np.array([[1,2,3],[4,5,6]])
Out[4]:
array([[1, 2, 3],
       [4, 5, 6]])

多次元配列のインデックスによるアクセス方法が複数あって、[index][index]という従来の方法に加えて、カンマ区切りでもアクセスできる。

In [5]: x = np.array([[1,2,3],[4,5,6]])

In [6]: x[0]
Out[6]: array([1, 2, 3])

In [7]: x[0][1]  # 従来の
Out[7]: 2

In [8]: x[0, 1]  # カンマ区切り
Out[8]: 2

NumPy配列の生成方法色々

指定したサイズですべて指定した要素の配列

In [3]: x = np.full((2,3), "foo")

In [4]: x
Out[4]:
array([['foo', 'foo', 'foo'],
       ['foo', 'foo', 'foo']], dtype='<U3')

通常のrangeと同じことをする

(開始値, 終了値, 増分)

In [5]: x = np.arange(10, 30, 5)

In [6]: x
Out[6]: array([10, 15, 20, 25])

整数のランダムな配列

In [7]: x = np.random.randint(0, 100, (3,3))

In [8]: x
Out[8]:
array([[33, 99, 94],
       [ 6,  1, 26],
       [15,  9, 46]])

その他

その他は公式のdoc参照
Array creation routines

Numpy配列のアクセス、操作

スライス

In [3]: x = np.array(range(10))

In [4]: x
Out[4]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [5]: x[:5]
Out[5]: array([0, 1, 2, 3, 4])

In [6]: x[5:]
Out[6]: array([5, 6, 7, 8, 9])

In [7]: x[1:3]
Out[7]: array([1, 2])

多次元配列

In [7]: x = np.array([range(10), range(10,20)])

In [8]: x
Out[8]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

In [9]: x[:1, :1]  # 最初の1行1列
Out[9]: array([[0]])

In [10]: x[:2, :4] # 最初の2行4列
Out[10]:
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13]])

In [11]:

スライスは複製ではなく参照になっているため変更すると元のデータが変更されることに注意。

In [11]: y = x[:2, :4]

In [12]: x
Out[12]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

In [13]: y
Out[13]:
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13]])

In [14]: y[0, 0] = 100

In [15]: x
Out[15]:
array([[100,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19]])

In [16]:

コピーしたいときは明示的にcopy()を使う

In [16]: y = x[:2, :4].copy()

ここまでは本当に基礎で、NumPy配列のメリットはその柔軟な操作や計算、統計処理だと思われます。
普段なんとなく適当にpandasを使っている感が否めないため、その基礎の学びなおし、を継続してみたいと思います。

Discussion