NumPyで特定の条件を満たす行、列を除去する方法

NumPyではスライシングで特定の条件を満たす要素だけ選択できる。逆の条件で使えば特定の要素だけ除去するのも簡単。

>>> array(range(5))
array([0, 1, 2, 3, 4])

>>> v = _
>>> v[v != 2]
array([0, 1, 3, 4])

これは「v != 2」の部分で演算子オーバーロードされていて、真偽値のarrayになっている。だからこれは他のarrayに対しても使える。

>>> v != 2
array([ True,  True, False,  True,  True], dtype=bool)

>>> randn(5)
array([ 1.96182557,  1.31524788, -0.09140969, -0.80362045,  0.02612784])

>>> _[v != 2]
array([ 1.96182557,  1.31524788, -0.80362045,  0.02612784])

ベクトルが縦になっているなら1つ目の軸に「:」(全部)を指定して2番目にスライスを指定すればよい。

>>> randn(5).reshape(1, 5)
array([[-0.86985953,  0.59620319, -1.25975869,  1.87290875, -0.44375606]])
>>> _[:, v != 2]
array([[-0.86985953,  0.59620319,  1.87290875, -0.44375606]])

ここまではTentative NumPy Tutorialにも書いてあるけど、今回やりたいことは正方行列の行と列と両方でこの除去をすること。

>>> array(range(25)).reshape(5, 5)

array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

>>> mat = _

単純に行と列の両方にこのスライシングを指定したらいいんじゃないか?って思うけどこれは間違い。対角成分だけになってしまう。

>>> mat[v != 2, v != 2]
array([ 0,  6, 18, 24])

片方をスライスしてからもう片方をスライスすればOK。

>>> mat[v != 2][:, v != 2]
array([[ 0,  1,  3,  4],
       [ 5,  6,  8,  9],
       [15, 16, 18, 19],
       [20, 21, 23, 24]])