Matching IDs Between Pandas DataFrames and Applying Function Matching IDs Between Pandas DataFrames and Applying Function numpy numpy

Matching IDs Between Pandas DataFrames and Applying Function


If ID isn't the index, make it so.

df_B.set_index('ID', inplace=True)df_A.set_index('ID', inplace=True)df_B['dist'] = ((df_A - df_B) ** 2).sum(1) ** .5

Since index and columns are already aligned, simply doing the math should just work.


Solution which uses sklearn.metrics.pairwise.paired_distances method:

In [73]: AOut[73]:    x  yIDa   0  0c   3  2b   2  5In [74]: BOut[74]:    x  yIDa   2  1c   3  5b   1  2In [75]: from sklearn.metrics.pairwise import paired_distancesIn [76]: B['dist'] = paired_distances(B, A)In [77]: BOut[77]:    x  y      distIDa   2  1  2.236068c   3  5  3.000000b   1  2  3.162278


For performance, you might want to work with NumPy arrays and for euclidean distance computations between corresponding rows, np.einsum would be do it pretty efficiently.

Incorporating the fixing of rows to make them aligned, here's an implementation -

# Get sorted row indices for dataframe-Asidx = df_A.index.argsort()idx = sidx[df_A.index.searchsorted(df_B.index,sorter=sidx)]# Sort A rows accordingly and get the elementwise differences against Bs = df_A.values[idx] - df_B.values# Use einsum to square and sum each row and finally sqrt for distancesdf_B['dist'] = np.sqrt(np.einsum('ij,ij->i',s,s))

Sample input, output -

In [121]: df_AOut[121]:    0  1a  0  0c  3  2b  2  5In [122]: df_BOut[122]:    0  1c  3  5a  2  1b  1  2In [124]: df_B  # After code runOut[124]:    0  1      distc  3  5  3.000000a  2  1  2.236068b  1  2  3.162278

Here's a runtime test comparing einsum against few other counterparts.