ここで道に沿ってnumpyの機能を利用してベクトル化されたアプローチだ -
# Convert strings in a to numeric labels
aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)
# Get the argsort for getting sorted keys from dictionary
dk = d.keys()
sidx = np.searchsorted(sorted(dk),dk)
# Extract values from d and sorted by the argsort indices.
# Then, index with the numeric labels from a and multiply with b.
d_vals= np.take(d.values(),sidx)
out = b*d_vals[aID]
キーは単一の文字であると想定されていることに注意してください文字列。彼らはその形式になっていない場合は、そのようなa
内の要素に対応する数値ラベル、取得するためにnp.unique
を使用することができます - このセクションでは
aID = np.unique(a,return_inverse=True)[1].reshape(a.shape)
ランタイムテスト
を、のは、それらの6 keys
と大きなを使ってみましょう配列や時間すべてのアプローチは、これまでの質問で提案されているオリジナルのものを含む投稿 -
In [238]: def original_app(a,b,d): # From question
...: c = np.zeros(a.shape)
...: for i in range(a.shape[0]):
...: for j in range(a.shape[1]):
...: c[i,j] = b[i,j] * d[a[i,j]]
...: return c
...:
...: def vectorized_app(a,b,d): # Proposed code earlier
...: aID = (np.fromstring(a, dtype=np.uint8)-97).reshape(a.shape)
...: dk = d.keys()
...: sidx = np.searchsorted(sorted(dk),dk)
...: d_vals= np.take(d.values(),sidx)
...: return b*d_vals[aID]
...:
In [239]: # Setup inputs
...: M, N = 400,500 # Dataisze
...: d = {'a': 600, 'b': 100, 'c': 700, 'd': 550, 'e': 200, 'f':80}
...: strings = np.array(d.keys())
...: a = strings[np.random.randint(0,6,(M,N))]
...: b = np.random.rand(*a.shape)
...:
In [240]: %timeit original_app(a,b,d)
1 loops, best of 3: 219 ms per loop
In [241]: %timeit b*np.vectorize(d.get)(a) # @TheBlackCat's solution
10 loops, best of 3: 34.9 ms per loop
In [242]: %timeit vectorized_app(a,b,d)
100 loops, best of 3: 3.17 ms per loop
In [243]: np.allclose(original_app(a,b,d),vectorized_app(a,b,d))
Out[243]: True
In [244]: np.allclose(original_app(a,b,d),b*np.vectorize(d.get)(a))
Out[244]: True
あなたのいずれかのいくつかのSORに重要なことで辞書要素にアクセスループを隠すか明示的にするか、またはキー/値/項目を使用してすべての値を取り出し、配列の使用に適した他の構造を作成します。 – hpaulj