おっぱいそん!

pythonを数値計算に使うときのテクニックとかをまとめていきたい。

Fancy Indexing:配列の一部を条件をつけて取り出す

aを適当なN次元配列とする。
a[a_1, a_2, a_3, ]とすると、配列の1つの成分を取り出せる。
a[リスト]とすると、1次元配列のリスト番目の成分のみ取り出した配列を返す。
(上の用に配列の1つの成分だけ取り出したい時にはtuple(リスト)のようにtupleにして渡せば良い)
a[リスト1,リスト2,リスト3, ]とすると、1次元目をリスト1で2次元目をリスト2で、といったように取り出した配列を返す。
np.ix_をつかってa[np.ix_([行],[列])]とすると行列の一部の行と列のみ取り出した新しい行列を作れる。
※ここまでのリストは配列にしても同じ。
同じことをbool値を使って、a[[行のbool],[列のbool],[3次元目のbool], ]とも出来る(これはリストにすると、False=0, True=1と解釈されるので注意)。

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print a[1,2]
print a[[1,2]]
print a[[1,2],[0,2]]
print a[np.ix_([1,2],[0,2])]
print a[np.array([False,True,True]),np.array([True,False,True])]

[[1 2 3]
[4 5 6]
[7 8 9]]
6
[[4 5 6]
[7 8 9]]
[4 9]
[[4 6]
[7 9]]
[4 9]

http://ibisforest.org/index.php?python%2Fnumpy#l9d00f8f

Numpyの配列(array)の一部を条件をつけて取り出す方法
import numpy as np
A = np.arange(10,0,-1)
print A>5
print np.where(A>5)
print A[A>5]**2
print A[np.where(A>5)]**2

[ True True True True True False False False False False]
(array([0, 1, 2, 3, 4]),)
[100 81 64 49 36]
[100 81 64 49 36]

配列に対して、論理式(>とか)を使うと、bool型(True or False)の配列を作ってくれる。
それを配列の引数として入れることで、配列の条件を満たす部分だけ取り出せる。
np.whereは基本的にタプルで条件が真の成分の場所を返す(返す値を別のものに指定も出来る)。
np.where(A>5)[0]とすれば、成分の場所を表すリストのみ渡してくれる。

【2014.10.23 追記】
2次元配列の例を追加しておく。

A = np.arange(9).reshape(3,3)
print A
print A>4
print np.where(A>4)
print A[A>4] # or A[np.where(A>4)]

[[0 1 2]
[3 4 5]
[6 7 8]]
[[False False False]
[False False True]
[ True True True]]
(array([1, 2, 2, 2]), array([2, 0, 1, 2]))
[5 6 7 8]

やはり、論理式は同じ形の配列で、成分がbool型のものを返す。
一方、np.whereはTrueの成分の場所を返す。今の場合は、Trueが4つあり、2次元配列なので、1つの成分の場所を指定するのに2つの数字がいるので、合計で8つの数字が並んでいる。
元の配列に論理式 or np.whereを入れると、元の配列が2次元でも、1次元配列として返す。

参考:
http://seesaawiki.jp/met-python/d/array
http://rest-term.com/archives/2999/
上の2つのサイトは配列の扱いに詳しい。
ひと通り読むといいかも。
http://d.hatena.ne.jp/nishiohirokazu/20111118/1321611727
http://www.geopacific.org/opensourcegis/python/python_raster

numpyのテンソル(配列)関係

numpy.transpose(a, axes=None)

配列の足の順番を入れ替える。
a:入れ替えたい配列
axes:順番の指定(指定なしなら、逆順になる)

import numpy as np

a = np.arange(24).reshape((2,3,4))
print a.shape
print np.transpose(a).shape
print a.transpose().shape
print np.transpose(a,(1,0,2)).shape

(2, 3, 4)
(4, 3, 2)
(4, 3, 2)
(3, 2, 4)

np.transpose(a)でもa.transpose()でも同じ役割
axesを指定しなければa[a_1,a_2,...,a_N]をa[a_N,...,a_2,a_1]に入れ替える。
http://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html


掛け算

a*b = np.multiply(a,b) は要素積
np.dot(a,b)は行列積(a,bが高次のテンソルの場合はaの最後の足とbの最後から2番目の足について掛ける)。
他にもいろいろな種類の掛け算が用意されてる。

multiply or *は基本的にa,bの配列の次元は同じでなければならない。
c[i,j,k,l] = a[i,j,k,l]b[i,j,k,l]
同じでない場合は、片方がスカラー
c[i,j,k,l] = ab[i,j,k,l]
もしくは、1次元配列
c[i,j,k,l] = a[l]b[i,j,k,l] #1次元配列と一方の配列の最後の要素の掛け算になる
でないとだめっぽい。
また、a*bとb*aは同じものを返すっぽい。

import numpy as np

A = np.arange(24).reshape((2,3,4))
B = np.array([1,2,3,4])
print A.shape
print B.shape
print (A*B).shape
print (B*A).shape
print np.multiply(A, B).shape

(2, 3, 4)
(4,)
(2, 3, 4)
(2, 3, 4)
(2, 3, 4)

http://ibisforest.org/index.php?python%2Fnumpy
http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html

【追記】任意の軸に関する要素積について、別に記事を書いたので、必要なら参照:
http://oppython.hatenablog.com/entry/2014/10/23/024831