雑多メモ

物忘れがひどいので、少なくとも自分がよく使う奴だけでも。
主にnumpyに絡む操作なので

import numpy as np

は既に実行した上での記述で書く。

slice関数:配列を扱うためのインデックスを抽象的に表現

例えば以下のように書くと1から無限(None指定)まで2おきのインデックスを作成。

>>> x = range(9)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> x[slice(1,None,2)]
[1, 3, 5, 7]

numpyの配列2本の直積集合を出す

以下のような感じでしょうか。meshgridで計算したものをdstackとreshapeで整形して出してる。

>>> x = np.arange(0,3,1)
>>> y = np.arange(0,3,1)
>>> print np.dstack(np.meshgrid(x, y)).reshape(-1, 2)
[[0 0]
 [1 0]
 [2 0]
 [0 1]
 [1 1]
 [2 1]
 [0 2]
 [1 2]
 [2 2]]

itertoolsを使っても書ける。ループで回すなら、こっちのほうがいいのかな。

>>> import itertools
>>> x = np.arange(0, 3, 1)
>>> y = np.arange(0, 3, 1)
>>> for val in itertools.product(x,y):
...     print val
(0, 0)
(0, 1)
(0, 2)
(1, 0)
(1, 1)
(1, 2)
(2, 0)
(2, 1)
(2, 2)

numpy配列の各次元の要素数を取得するにはshape関数を使う

>>> np.shape(np.array([[1,2,3],[4,5,6]]))
(2, 3)
>>> 

numpy配列の各要素に対して関数を適用(Rでいうapply系の書き方)

>>> f = np.vectorize(lambda x:100*x)
>>> y = np.array([1,2,3])
>>> f(y) 
array([100, 200, 300])

二次元配列のソートにはlexsort関数を使う

以下の例だと行ごとの値を1列目→2列目と比較して、その昇順インデックスを返却。

>>> x = np.array([[1,2],[3,4],[1,3]])
>>> x

array([[1, 2],
       [3, 4],
       [1, 3]])
>>> np.lexsort(x.T)
array([0, 2, 1])

2次元配列に対する重複削除:unique

上述のlexsortを使った実装が以下にあって、なかなかよい。
python - Removing duplicate columns and rows from a NumPy 2D array - Stack Overflow

divmodで商・剰余のタプルを得る

同時に出るのありがたい。
以下の例だと10÷3の商(3)と剰余(1)を出してる。

>>> divmod(10,3)
(3, 1)

配列のソートにはsort関数、そのインデックスが欲しければargsort関数を使う

適当に作ったnumpy.arrayをソートするって話。
ソート関数は自身の配列を変更してしまう点に注意。

>>> x = np.array(np.random.normal(size=5))
>>> x
array([ 0.64180922, -0.68737811, -0.56254886, -1.05192228,  1.47702876])
>>> x.argsort()
array([3, 1, 2, 0, 4])
>>> x[x.argsort()]
array([-1.05192228, -0.68737811, -0.56254886,  0.64180922,  1.47702876])
>>> x.sort()
>>> x
array([-1.05192228, -0.68737811, -0.56254886,  0.64180922,  1.47702876])

配列(numpy.array)からの指定条件を満たすインデックスの抽出

numpy.where関数を使うといいのか、これが正しい書き方かわからんけどメモ。
詳細な使い方はリファレンス見てもよくわからん。

>>> x = np.array([1,2,3,4,5])
>>> np.where(x > 2)
(array([2, 3, 4]),)
>>> np.where(x == 2)
(array([1]),)
>>> np.where(x == 2)[0][0]
1
>>> x[1]
2

出力が多次元配列対応されているため、いちいち[0][0]と書かないと数にもっていけないのが辛い。
2次元配列でやってみると、もっとめんどい。

>>> x = np.array([[1,2,3], [4,5,6]])
>>> x
array([[1, 2, 3],
       [4, 5, 6]])
>>> np.where(x == 3)
(array([0]), array([2]))
>>> np.where(x > 3)
(array([1, 1, 1]), array([0, 1, 2]))

返り値をどうやって捌くかでまた美しい方法を考える必要がある。

pythonのlistだとindexメソッドでもっと素直に書けるのに。。。

>>> a = [10,15,20]
>>> a.index(15)
1
>>> 

似たような関数でargwhereなるものもあるらしい。

where関数の出力と比較してみると

>>> np.argwhere(x > 3)
array([[1, 0],
       [1, 1],
       [1, 2]])
>>> np.where(x > 3)
(array([1, 1, 1]), array([0, 1, 2]))
>>> 

2d-array(argwhere)かarrayのtuple(where)かが違うと言うところか。

一番よく使いそうな1次元配列の例も、よく忘れるのでもう一回書いておく。

>>> x = np.array([1,2,3,4,5])
>>> np.where(x > 3)
(array([3, 4]),)
>>> np.argwhere(x > 3)
array([[3],
       [4]])

配列のインデクシング

実はこいつも良く忘れる。
特に−1は最終要素で、配列の要素は[tuple]でもアクセス可能な事を覚えておく事。
あとスライシング系も。

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