NumPyで行列を各column単位でイテレートするには
追記:結論としてはtransposeはデータのコピーをしないので気兼ねなく使ってOK。
まず「各column単位でイテレートしたい」が理解してもらいにくいので簡単に説明する。
ある行列matがあったとする。
In [125]: array([[1, 2], [3, 4]]) Out[125]: array([[1, 2], [3, 4]]) In [126]: mat = _
これを普通にイテレートすると各row単位でイテレートする。
In [139]: for v in mat: print v [1 2] [3 4]
で、そうじゃなくて[1 3] [2 4]とcolumn単位でイテレートしたい場合には、どうするのがスマートだろうか?もちろんtransposeしてしまうというのはひとつの手。
In [140]: for v in mat.transpose(): print v [1 3] [2 4]
だけど、array#transposeはイテレータではなく、行列をまるっとコピーしてしまう。将来的に行列が大きくなった場合のことを考えると、イテレートのためだけにtransposeはしたくない。追記:これは事実誤認でtransposeでコピーはされない。
shapeとrangeとスライシングで作るというのはもう一つの手だ。これは関数にまとめておくことができるので可読性をあまり損ねることなく使える。
In [141]: [mat[:, i] for i in range(mat.shape[1])] Out[141]: [array([1, 3]), array([2, 4])] In [142]: def iter_column(mat): .....: return (mat[:, i] for i in xrange(mat.shape[1])) .....: In [143]: for v in iter_column(mat): print v [1 3] [2 4]
で、疑問なのは、なんでこれがarrayのメソッドになってないのかということ。それともどこかにユーティリティ関数として置かれてたりするのかな?まだ見つけられていない。