データ行列に対して各行毎にアレイで定義された範囲内の最小値を探す

Vectorize a numpy.argmin search with a variable range per matrix row – StackOverflow

import numpy as np

np.random.seed(10)

data = np.random.random((6, 100))
ranges = np.array(
    [
        [0.3, 0.4],
        [0.35, 0.5],
        [0.45, 0.6],
        [0.52, 0.65],
        [0.6,  0.8],
        [0.75,  0.92]
    ]
)
result = np.zeros(6, dtype=np.int)
for i in range(6):
    ind = np.where((ranges[i][0] <= data[i]) & (data[i] <= ranges[i][1]))[0]
    #ind = np.argwhere((ranges[i][0] <= data[i]) & (data[i] <= ranges[i][1]))
    result[i] = ind[np.argmin(data[i, ind])]

print(result)
print(data[np.arange(6), result])

[35 8 22 8 34 78]
[ 0.30070006 0.35065639 0.45784951 0.52885388 0.61393513 0.75449247]

というのをループを使わずに処理するにはどうすれば良いか.

まず,最小値が欲しい訳だから,column-wiseでソートしておく(numpy.sort(axis=1)).
後は範囲を表すnumpy.ndarrayをブロードキャストしてやれば良い.

data.sort(axis=1)
ind = np.where((ranges[:, 0, np.newaxis] <= data) & (data <= ranges[:, 1, np.newaxis]))
c_ind = np.unique(ind[0], return_index=True)[1]
print(ind[1][c_ind])
print(data[ind[0][c_ind], ind[1][c_ind]])

[26 36 47 52 54 79]
[ 0.30070006 0.35065639 0.45784951 0.52885388 0.61393513 0.75449247]

最初のインデックス位置まで欲しい場合は,破壊的ソートではなくコピーを用意する.

data = np.random.random((6, 100))
result = np.zeros(6, dtype=np.int)
for i in range(6):
    ind = np.argwhere((ranges[i][0] <= data[i]) & (data[i] <= ranges[i][1]))
    result[i] = ind[np.argmin(data[i, ind])]

print(result)
print(data[np.arange(6), result])

[64 63 11 65 61 57]
[ 0.30568034 0.35152159 0.4564369 0.53575571 0.60476683 0.77502898]

sort_data = np.sort(data, axis=1)
ind_data = np.lexsort([np.ones((6, 100))*np.arange(100), data])
ind = np.where((ranges[:, 0, np.newaxis] <= sort_data) & (sort_data <= ranges[:, 1, np.newaxis]))
c_ind = np.unique(ind[0], return_index=True)[1]
print(ind_data[ind[0][c_ind], ind[1][c_ind]])
print(sort_data[ind[0][c_ind], ind[1][c_ind]])

[64 63 11 65 61 57]
[ 0.30568034 0.35152159 0.4564369 0.53575571 0.60476683 0.77502898]

data.sort(axis=1)
ind = np.where((ranges[:, 0, np.newaxis] <= data) & (data <= ranges[:, 1, np.newaxis]))
c_ind = np.unique(ind[0], return_index=True)[1]
print(ind[1][c_ind])
print(data[ind[0][c_ind], ind[1][c_ind]])

[28 29 53 63 61 79]
[ 0.30568034 0.35152159 0.4564369 0.53575571 0.60476683 0.77502898]

広告
カテゴリー: 未分類 パーマリンク

データ行列に対して各行毎にアレイで定義された範囲内の最小値を探す への1件のフィードバック

  1. ピンバック: 粉末@それは風のように (日記)

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中