(3,3)(順に点0,...,点3とする)として与えられている。クラスのインスタンス化のときに与えられているn_neighbors=3は、k最近傍のkを表していて、つまりここでは各点から一番近い3点ずつを計算する。結果は2つの変数distancesとindicesに入れられていて、indicesは各点から近い順に点のインデックスが入っている。行1と表現する)には点iから近い順に点のインデックスが入っている。ここで行1が[1,0,2]なのは、点1から近い順に点1、点0、点2であるということである。問題提起レコメンデーションシステムや情報検索の分野では、自分自身を除いて最近傍をとりたいことがよくある。点Xから近いもののリストに点Xが入っていてほしくない。いうものを取得するにはどうすればよいだろうか。distanceもindicesも両方とも自分自身を除いたものにしたい。一瞬、自分自身が必ず一番近いから一番左の列を削ればいいのではと思うかもしれないが、話はそう単純ではない。dtype=int64)この場合は、行1の一番左に0がくるが、この行からも1を取り除きたい。やっかいなのは、行iにiが含まれないこともある。dtype=int64)これは極端な例だが、行3には3が含まれていない。ここで2近傍を計算するときは行3は一番右を消して[0,1]にならないといけない。やりたいことの仕様をまとめると次のようになる。行列indicesの各行について、行iにiという値があればその値を削除する行iにiという値がなければ一番右の値を削除する以上の削除により元のindicesより1列少ない行列を取得する行列distancesについても、indicesで削除された要素と同じ位置の要素を削除して1列少ない行列を取得するこのことをNumpyの機能を駆使してfor文を使わずにやりたい。for文使ったら負けだと思っているので。解説ここではなぜそのようなコードになるのかという理由を解説するので、コードだけを知りたい場合は読み飛ばして「結論」を参照されたい。次のような人工的なindicesとdistancesを用意して計算してみる。21]])方針としては、削除するべき要素がFalseでそれ以外をTrueにしたマスク行列を用意して、インデキシングを利用して抽出する。行iで要素がiであるものをFalseにするには次のような計算をする。dtype=bool)ここでは演算子!=がブロードキャストされて各要素の比較が行われている。indicesの行数をnとすると、演算子!=の右辺はn行1列で0~n-1が順に入った行列を意味している。indicesの各要素と、右辺の行列の対応する行の値が比較されている。次に、一番下の行がすべてTrueなのでこの一番右をFalseにしたい。一般にはすべてがTrueな行の一番右をFalseに書き換えたい。各行について「すべてがTrueか?」はこれで判定できる。dtype=bool)ここでallは要素の論理積をとるメソッドで、引数axis=1が指定されているのは横方向に計算することを意味している。この結果のnotをとって、maskの一番右の列との論理積をとり、maskの一番右の列に格納しなおせばよい。dtype=bool)これでマスク行列ができたので、これをindicesとdistancesに適用すればいいのだが、2次元配列にインデキシングすると1次元配列になってしまうのでreshapeする必要がある。20]])これでほしい結果が得られた。次のコードでやりたいことができる。indicesとdistancesを上書きしている。コメントをキャンセルメールアドレスが公開されることはありません。