例えばたくさんの点の座標値が配列に入っていると考えてください。

この点同士の全組み合わせの距離を計算したい、あるいは一番近い点同士を見つけたいなどのタスクはnumpyだとちょっとだけめんどうです。毎回忘れるのでメモします。

>>> import numpy as np
>>> positions = np.array([[0, 0, 0], [5, 5, 5], [1, 2, 10], [-3, 0, -2]])
>>> positions.shape
(4, 3)

こんな感じで、xyz座標で表される3次元ユークリッド空間上の点が4つあるとしましょう。

この中で、一番距離が近い点の組み合わせはどれか?

それを知るためには、点同士の全組み合わせの距離を計算しなければなりません。素直にfor文で計算していたらマサカリが飛んでくるかサービスが完成しないでしょう。そして、そのためにnumpyは存在します。

以下のようにして、全組み合わせの距離を得ることができます。

>>> tmp_index = np.arange(positions.shape[0])
>>> xx, yy = np.meshgrid(tmp_index, tmp_index)
>>> distances = np.linalg.norm(positions[xx]-positions[yy], axis=2)
>>> distances
array([[ 0.        ,  8.66025404, 10.24695077,  3.60555128],
       [ 8.66025404,  0.        ,  7.07106781, 11.74734012],
       [10.24695077,  7.07106781,  0.        , 12.80624847],
       [ 3.60555128, 11.74734012, 12.80624847,  0.        ]])

新たに(4, 4)のarray distancesが得られました。distances[i][j]には、最初に定義したarray positionsのi番目の点とj番目の点の間の距離が格納されています。

meshgridから返ってきたxx, yyは同じ次元の配列になっていて、走査することでtmp_indexの全組み合わせを探索することができます。なんて便利な!!

>>> xx
array([[0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3]])
>>> yy
array([[0, 0, 0, 0],
       [1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3]])

ここからは簡単ですね。同じ点同士を計算している対角成分をnanとすれば、nanminで最小値が取得できる状態になります。

>>> np.fill_diagonal(distances, np.nan)
>>> np.nanmin(distances)
3.605551275463989

ここから最小値を持つインデックスを求めるには、nanargminとunravel_indexを使うとできます。

>>> np.unravel_index(np.nanargmin(distances), distances.shape)
(0, 3)

 

0番目の点と3番目の点、すなわち点[0, 0, 0]と点[-3, 0, -2]の間の距離が3.605551275463989で最小であることがわかりました。

argminやnanargmin, argmax等を複数次元の配列に適用する方法は実は今回初めて知りました。unravel_index便利ですね。

 

関連記事

fitbitの睡眠スコアを90弱で安定させる良い睡眠を続ける簡単な方法

m1 ipad pro 12.9 2021のusb-cハブはコレがベスト

Time Machine不要!Macを11.2.3にダウングレードして原神をm1 macbook airでプレイする

MH-Z19CとM5StickCで二酸化炭素濃度モニタリング

【神軽量HMD】Avegant Glyph 改造: 瓶詰堂さんのaltglyphを作った

PC、iPad、Android、switchもドックいらず!あまりに万能なusb-cハブが最強だった

コメント

コメントを返信する

メールアドレスが公開されることはありません。 が付いている欄は必須項目です