Hi
Using loops is a bottleneck in term of performance; I’m often facing such issue, I’m not satisfied by the current code and I’m still looking for a way to speed-up it. Each element is checked one at a time; some numpy functions cannot be used: np.intersect1d for example
Of course I’ll have a look to parallelization, but I’m wondering if somebody has ever found a better solution?
Here and for each element of the 1rst column of the GP array, the goal is to add a column with the corresponding value of the 2nd column of the M array; note in GP, values are not unique, they are not sorted, and they do not necessarily follow each other.
Note it's here a test case; in the "real life", I'm dealing with hundreds millions of rows
Thanks
Paul
Using loops is a bottleneck in term of performance; I’m often facing such issue, I’m not satisfied by the current code and I’m still looking for a way to speed-up it. Each element is checked one at a time; some numpy functions cannot be used: np.intersect1d for example
Of course I’ll have a look to parallelization, but I’m wondering if somebody has ever found a better solution?
Here and for each element of the 1rst column of the GP array, the goal is to add a column with the corresponding value of the 2nd column of the M array; note in GP, values are not unique, they are not sorted, and they do not necessarily follow each other.
Note it's here a test case; in the "real life", I'm dealing with hundreds millions of rows

Thanks
Paul
import numpy as np import time M = np.array([[ 1, 2], [ 2, 5], [ 3, 7], [ 4, 2], [ 50, 5], [ 6, 11], [ 70, 5], [ 8, 11], [ 100, 2]] ) GP = np.array([[ 1, 1, 100], [ 1, 2, 100], [ 1, 5, 100], [ 1, 3, 100], [ 1, 4, 100], [ 3, 1, 100], [ 3, 2, 100], [ 3, 3, 100], [ 3, 4, 100], [ 70, 3, 90], [ 70, 4, 90], [ 70, 2, 92], [ 70, 2, 93], [ 6, 1, 100], [ 6, 8, 100], [ 6, 5, 100], [ 6, 4, 100], [ 6, 3, 100], [ 6, 7, 100], [ 6, 2, 100], [ 6, 6, 100]] ) # GP size is increased for time purpoase n = 20 for j in range(n): GP = np.vstack((GP, GP)) r1, c1 = np.shape(M) r2, c2 = np.shape(GP) ####################################################### # solution 1 : start from each element in M even if it does not exist R1 = np.zeros(r2) t0 = time.time() for i in range(r1): Index = np.where(GP[:, 0].reshape(-1, 1) == M[i, 0])[0] R1[Index] = M[i, 1] t1 = time.time() print(f"Duration Solution1 = {(t1 - t0):.2e}") ####################################################### # solution 2 : only existing elements in GP are dealt R2 = np.zeros( (r2, 1)) t2 = time.time() t2_1 = time.time() UniqueSortedElement, ReturnIndex, ReturnInverse, ReturnOccurences = np.unique(GP[:, 0], return_index = True, return_inverse = True, return_counts = True) t2_2 = time.time() n = np.shape(UniqueSortedElement)[0] tempo = np.zeros(n) for i in range(n): Index = np.where(M[:, 0].reshape(-1, 1) == UniqueSortedElement[i])[0] tempo[i] = M[Index, 1] t2_3 = time.time() R2 = tempo[ReturnInverse] # we've been using the "return_inverse" capability to build the R2 matrix t3 = time.time() print(f"Duration Solution2 = {(t3 - t2):.2e}") print(f"\t-interm1 = = {(t2_2 - t2_1):.2e}") print(f"\t-interm2 = = {(t2_3 - t2_2):.2e}") print(f"\t-interm3 = = {(t3 - t2_3):.2e}") Check = np.array_equal(R1, R2) print(f"Are R1 and R2 identical : {Check}") # finally a new column is added to GP GP = np.hstack((GP, R1.reshape(-1, 1)))