簡體   English   中英

Numpy:基於dict的值創建2D數組,使用其他2D數組值作為索引

[英]Numpy: Create 2D array based on value from dict, using other 2D array value as index

我有2個2D 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]])

我有一個帶有一些值的字典:

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

現在我想創建一個基於前2個和我的dict的2D數組。 像這樣的東西:

c = b * d[a]

換句話說,我想使用對應於同一索引處的數組a中的值的特定值(從dict d檢索)來操縱數組b

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

除了嵌套循環之外,還有什么方法可以做到這一點嗎?

您可以使用矢量化的功能d.get方法使用的值a為鍵d

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

請注意,這是在幕后實現的循環,因此它不會給您帶來太多(如果有的話)性能優勢。

您可以將其合並為一行:

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

這是一種利用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]

請注意,假設鍵是單字符串。 如果他們不是在格式,你可以使用np.unique獲得對應於要素數字標簽a ,像這樣-

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM