更新:如@root所指出,在这种情况下使用欧几里得度量并不是很有意义,因此让我们使用sklearn.neighbors.DistanceMetric
from sklearn.neighbors import DistanceMetric
dist = DistanceMetric.get_metric('haversine')
首先,我们可以使用所有组合构建一个DF - (c) root:
x = pd.merge(df1.assign(k=1), df2.assign(k=1), on='k', suffixes=('1', '2')) \
.drop('k',1)
向量化的“haversine”距离计算
x['dist'] = np.ravel(dist.pairwise(np.radians(df1),np.radians(df2)) * 6367)
结果:
In [86]: x
Out[86]:
lat1 lon1 lat2 lon2 dist
0 38.32 -100.50 37.65 -97.87 242.073182
1 38.32 -100.50 33.31 -96.40 667.993048
2 38.32 -100.50 36.22 -100.01 237.350451
3 42.51 -97.39 37.65 -97.87 541.605087
4 42.51 -97.39 33.31 -96.40 1026.006744
5 42.51 -97.39 36.22 -100.01 734.219411
6 33.45 -103.21 37.65 -97.87 671.274044
7 33.45 -103.21 33.31 -96.40 632.004981
8 33.45 -103.21 36.22 -100.01 424.140594
新回答:
如果我理解正确,您可以使用成对距离 scipy.spatial.distance.pdist:
In [32]: from scipy.spatial.distance import pdist
In [43]: from itertools import combinations
In [34]: X = pd.concat([df1, df2])
In [35]: X
Out[35]:
lat lon
0 38.32 -100.50
1 42.51 -97.39
2 33.45 -103.21
0 37.65 -97.87
1 33.31 -96.40
2 36.22 -100.01
作为 Pandas.Series:
In [36]: s = pd.Series(pdist(X),
index=pd.MultiIndex.from_tuples(tuple(combinations(X.index, 2))))
In [37]: s
Out[37]:
0 1 5.218065
2 5.573240
0 2.714001
1 6.473801
2 2.156409
1 2 10.768287
0 4.883646
1 9.253113
2 6.813846
2 0 6.793791
1 6.811439
2 4.232363
0 1 4.582194
2 2.573810
1 2 4.636831
dtype: float64
作为 Pandas.DataFrame:
In [46]: s.rename_axis(['df1','df2']).reset_index(name='dist')
Out[46]:
df1 df2 dist
0 0 1 5.218065
1 0 2 5.573240
2 0 0 2.714001
3 0 1 6.473801
4 0 2 2.156409
5 1 2 10.768287
6 1 0 4.883646
7 1 1 9.253113
8 1 2 6.813846
9 2 0 6.793791
10 2 1 6.811439
11 2 2 4.232363
12 0 1 4.582194
13 0 2 2.573810
14 1 2 4.636831