すでにお使いの方法で、
A[list1, :][:, list2]
スペアマトリックスから目的の値を選択する最速の方法のようです。ベンチマークについては、以下を参照してください。
A
ただし、単一のインデックスを使用して任意の行と列から値を選択する方法に関する質問に答えるには、いわゆる「高度なインデックス作成」を使用する必要があります。
A[np.array(list1)[:,np.newaxis], np.array(list2)]
高度なインデックス付けでは、arr1
とarr2
が NDarrayの場合、 equalsの(i,j)
コンポーネントA[arr1, arr2]
A[arr1[i,j], arr2[i,j]]
したがって、 equal for allと
arr1[i,j]
equal for all が必要になります。list1[i]
j
arr2[i,j]
list2[j]
i
これは、ブロードキャスト(以下を参照) を
使用してarr1 = np.array(list1)[:,np.newaxis]
、 とを設定することで調整できますarr2 = np.array(list2)
。
必要に応じて左側に新しい軸が自動的に追加されるため、 arr1
isの形(len(list1), 1)
はarr2
is
(len(list2), )
which にブロードキャストされます。(1, len(list2))
各配列はさらに shape にブロードキャストできます(len(list1),len(list2))
。shape の結果配列のすべての可能なインデックスを実行したいので、これはまさに私たち
A[arr1[i,j],arr2[i,j]]
が意味を成すために望んでいることです。(i,j)
(len(list1),len(list2))
A[list1, :][:, list2]
これが最速のオプションであることを示唆する 1 つのテスト ケースのマイクロベンチマークです。
In [32]: %timeit orig(A, list1, list2)
10 loops, best of 3: 110 ms per loop
In [34]: %timeit using_listener(A, list1, list2)
1 loop, best of 3: 1.29 s per loop
In [33]: %timeit using_advanced_indexing(A, list1, list2)
1 loop, best of 3: 1.8 s per loop
ベンチマークに使用したセットアップは次のとおりです。
import numpy as np
import scipy.sparse as sparse
import random
random.seed(1)
def setup(N):
A = sparse.rand(N, N, .1, format='lil')
list1 = np.random.choice(N, size=N//10, replace=False).tolist()
list2 = np.random.choice(N, size=N//20, replace=False).tolist()
return A, list1, list2
def orig(A, list1, list2):
return A[list1, :][:, list2]
def using_advanced_indexing(A, list1, list2):
B = A.tocsc() # or `.tocsr()`
B = B[np.array(list1)[:, np.newaxis], np.array(list2)]
return B
def using_listener(A, list1, list2):
"""https://stackoverflow.com/a/26592783/190597 (listener)"""
B = A.tocsr()[list1, :].tocsc()[:, list2]
return B
N = 10000
A, list1, list2 = setup(N)
B = orig(A, list1, list2)
C = using_advanced_indexing(A, list1, list2)
D = using_listener(A, list1, list2)
assert np.allclose(B.toarray(), C.toarray())
assert np.allclose(B.toarray(), D.toarray())