在 Pandas 个数据帧之间匹配 ID 并应用函数
Matching IDs Between Pandas DataFrames and Applying Function
我有两个如下所示的数据框:
df_A:
ID x y
a 0 0
c 3 2
b 2 5
df_B:
ID x y
a 2 1
c 3 5
b 1 2
我想在 db_B 中添加一列,即每个标识符的 df_B 和 df_A 中的 x,y 坐标之间的欧几里得距离。期望的结果是:
ID x y dist
a 2 1 1.732
c 3 5 3
b 1 2 3.162
标识符不一定要按相同的顺序排列。我知道如何通过遍历 df_A 的行并在 df_B 中找到匹配的 ID 来做到这一点,但我希望避免使用 for 循环,因为这将用于数千万的数据的行。有没有什么方法可以使用 apply 但以匹配的 ID 为条件?
如果 ID
不是索引,请将其设为索引。
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
由于索引和列已经对齐,简单地计算一下就可以了。
使用sklearn.metrics.pairwise.paired_distances方法的解决方案:
In [73]: A
Out[73]:
x y
ID
a 0 0
c 3 2
b 2 5
In [74]: B
Out[74]:
x y
ID
a 2 1
c 3 5
b 1 2
In [75]: from sklearn.metrics.pairwise import paired_distances
In [76]: B['dist'] = paired_distances(B, A)
In [77]: B
Out[77]:
x y dist
ID
a 2 1 2.236068
c 3 5 3.000000
b 1 2 3.162278
为了提高性能,您可能希望使用 NumPy 数组并计算相应行之间的欧氏距离,np.einsum
会非常高效。
合并行的固定以使其对齐,这是一个实现 -
# Get sorted row indices for dataframe-A
sidx = 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 B
s = df_A.values[idx] - df_B.values
# Use einsum to square and sum each row and finally sqrt for distances
df_B['dist'] = np.sqrt(np.einsum('ij,ij->i',s,s))
样本输入、输出-
In [121]: df_A
Out[121]:
0 1
a 0 0
c 3 2
b 2 5
In [122]: df_B
Out[122]:
0 1
c 3 5
a 2 1
b 1 2
In [124]: df_B # After code run
Out[124]:
0 1 dist
c 3 5 3.000000
a 2 1 2.236068
b 1 2 3.162278
这里是 比较 einsum
和少数其他同行。
我有两个如下所示的数据框:
df_A:
ID x y
a 0 0
c 3 2
b 2 5
df_B:
ID x y
a 2 1
c 3 5
b 1 2
我想在 db_B 中添加一列,即每个标识符的 df_B 和 df_A 中的 x,y 坐标之间的欧几里得距离。期望的结果是:
ID x y dist
a 2 1 1.732
c 3 5 3
b 1 2 3.162
标识符不一定要按相同的顺序排列。我知道如何通过遍历 df_A 的行并在 df_B 中找到匹配的 ID 来做到这一点,但我希望避免使用 for 循环,因为这将用于数千万的数据的行。有没有什么方法可以使用 apply 但以匹配的 ID 为条件?
如果 ID
不是索引,请将其设为索引。
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
由于索引和列已经对齐,简单地计算一下就可以了。
使用sklearn.metrics.pairwise.paired_distances方法的解决方案:
In [73]: A
Out[73]:
x y
ID
a 0 0
c 3 2
b 2 5
In [74]: B
Out[74]:
x y
ID
a 2 1
c 3 5
b 1 2
In [75]: from sklearn.metrics.pairwise import paired_distances
In [76]: B['dist'] = paired_distances(B, A)
In [77]: B
Out[77]:
x y dist
ID
a 2 1 2.236068
c 3 5 3.000000
b 1 2 3.162278
为了提高性能,您可能希望使用 NumPy 数组并计算相应行之间的欧氏距离,np.einsum
会非常高效。
合并行的固定以使其对齐,这是一个实现 -
# Get sorted row indices for dataframe-A
sidx = 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 B
s = df_A.values[idx] - df_B.values
# Use einsum to square and sum each row and finally sqrt for distances
df_B['dist'] = np.sqrt(np.einsum('ij,ij->i',s,s))
样本输入、输出-
In [121]: df_A
Out[121]:
0 1
a 0 0
c 3 2
b 2 5
In [122]: df_B
Out[122]:
0 1
c 3 5
a 2 1
b 1 2
In [124]: df_B # After code run
Out[124]:
0 1 dist
c 3 5 3.000000
a 2 1 2.236068
b 1 2 3.162278
这里是 einsum
和少数其他同行。