Python
numpy

Numpy を使わない多次元配列計算 その2

More than 1 year has passed since last update.

Numpyを使わない多次元配列計算

以前に、http://qiita.com/ponnhide/items/c919f3bc549d1228c800 の記事で、numpyを用いない配列計算について取り扱ったが、この記事はその発展版

なぜnumpyを使わないか。

numpyを使えばできるのに、何故使わない方法を考えるか。ただの趣味という側面もあるが、単にpypy上でnumpyを使うと異常に実行が遅くなるためである。まぁきっと他にも使い道はあると思う。

前回の復習(加減乗除)

前回の記事で、「mapとlambdaを駆使すれば、配列同士の演算はおちゃのこさいさい」とか書いてしまったがぶっちゃけlambdaよりは、operatar モジュールを使った方がはるかにスクリプトが簡素ですむ。operator モジュールを使うと、演算子を関数形式で用いることができる。例えば、operator.add(a,b)a+b と同義である。

まずは
1次元配列の和

from operator import add
>>> array1 = [4,5,6]
>>> array2 = [1,2,3]
>>> list(map(add, array1, array2))
[5,7,9]

2次元配列の和
結局、ここではlambdaを使うわけだが、

>>> array1 = [[1,2,3],[1,2,3]]
>>> array2 = [[2,3,4],[2,3,4]]
>>> list(map(lambda x,y: list(map(add, x,y)), array1, array2))
[[3, 5, 7], [3, 5, 7]]

どうしてもlambdaには頼らないぞっていう場合は、リスト内包表記をつかって、

>>> [list(map(add, x,y)) for x,y in zip(array1,array2)]
[[3, 5, 7], [3, 5, 7]]

みたいな書き方もできる。こっちの方がスッキリしてるか。

行列の掛け算

前回は扱わなかったが、numpyを使わずにと豪語するなら、やっぱり行列の掛け算(要素同士の積じゃなくてdot積)もやるべきだろということで、無理やり考えてみた。

>>> from operator import mul
>>> array1 = [[2,3],[1,4],[2,1]]
>>> array2 = [[3,1,2],[2,4,2]]
>>> [[sum(map(mul, row, col)) for col in zip(*array2)] for row in array1]
[[12, 14, 10], [11, 17, 10], [8, 6, 6]]

よしできた。しかし、array1が 1行xn列 の場合だと上記の書き方ではできない。array1が 1行xn列 場合は、

>>> from operator import mul
>>> array1 = [1,0,0,1]
>>> array2 = [[0,1],[1,1],[1,0],[1,0]]
>>> [sum(map(mul, array1, col)) for col in zip(*array2)]
[1,1]

うーむ。lambdaや、三項演算子を駆使すれば、統一した書き方もできるかな。。

統計関連

特に使い方には触れないが、python3.4以降の環境ならデフォルトで、statistics モジュールが入っている。これを使えば、list型のまま基本的な統計量は計算が可能。
https://docs.python.jp/3/library/statistics.html