I have an input_array of shape (m, n, 2) and a dictionary mapping (Dict[Tuple[int, int], float]). I like to create a new (m, n) output_array by replacing the inner most arrays in the input_array based on the mapping dictionary.
Example:
input_array = np.array([[[1, 2], [3, 7]], [[1, 2], [4, 5]]])
mapping = {(1, 2): 0.7, (3, 7): 0.8, (4, 5): 0.9, (2, 4): 0.3}
---
output_array = np.array([[0.7, 0.8], [0.7, 0.9]])
Attempt:
import time
import numpy as np
def map_values(input_array, mapping):
output_array = np.empty(input_array.shape[:2], dtype=float)
tic = time.time()
for key in np.unique(input_array.reshape(-1, 2), axis=0):
value = mapping[tuple(key)]
mask = np.all(input_array == key, axis=-1)
indices = np.where(mask)
output_array[indices[0], indices[1]] = value
toc = time.time()
print(f'mapping loop took {toc-tic:.4f} seconds')
return output_array
Is there a way to make the looping and replacement of arrays faster?
I would use a simple loop:
Or, if you expect many duplicated values, you could reduce the mapping step to the unique values, although the bottleneck being
np.uniquethis might not be much faster ifnis large:Output:
timings
On (2, 2, 2):
On (200, 200, 2):
For large
m(orn) (2000, 2, 2):For large
mandn(e.g. (2000, 2000, 2)):As noted by @MatBailie, the simple loop can be further improved using
np.fromiter: