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