2016-06-24 20 views
1

として他の2次元配列の値を使用して、辞書からの値に基づいて、2次元配列を作成します。numpyの:私は2次元のnumpyのアレイを有する指標

a = np.array([['a', 'b', 'c'], ['d', 'e', 'f']]) 
b = np.array([[0.01, 0.02, 0.03], [0.04, 0.05, 0.06]]) 

を私はいくつかの値を持つ辞書を持っているASO:

d = {'a': 100, 'b': 200, ... 'f':600} 

今、最初の2つと私の辞書に基づいて2次元配列を作成したいと思います。このようなもの:すなわち

c = b * d[a] 

、Iは同じインデックスで配列aの値に対応する(辞書dから取得)特定の値を使用して、アレイbを操作します。

c = np.array([[1, 4, 9], [16, 25, 36]]) 

ネストされたループの他にこれを行う方法はありますか?

+0

あなたのいずれかのいくつかのSORに重要なことで辞書要素にアクセスループを隠すか明示的にするか、またはキー/値/項目を使用してすべての値を取り出し、配列の使用に適した他の構造を作成します。 – hpaulj

答えて

0

あなたはdのためのキーとしてaの値を使用するd.get方法にvectorize機能を使用することができます。それはあなたを与えることはありませんので、これは舞台裏ループとして実装されていること

>>> np.vectorize(d.get)(a) 
array([[100, 200, 300], 
     [400, 500, 600]]) 

注意をパフォーマンス上のメリット(あれば)もあります。

あなたは1行にこれを組み合わせることができます。

>>> b*np.vectorize(d.get)(a) 
array([[ 1., 4., 9.], 
     [ 16., 25., 36.]]) 
0

ここで道に沿って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 
+0

これはベクトル化されていますが、一意の値とソートと検索を取得すると、ベクトル化のスピードを失います。 – TheBlackCat

+0

@TheBlackCat確かに、ベクトル化をセットアップするためのオーバーヘッドがあります。私は入力データ形式に依存すると思います。 'd'でキーの数が限られていることを期待していますので、そこでのソートはそれほどコストがかかりません。それがOPとどのようにパンを見てみましょう。 – Divakar

+0

@TheBlackCatさて、 'np.unique'を取り除いた!今はるかに速くなければならない、フィードバックのために多くの感謝! – Divakar

関連する問題