根据数据框之间的距离和 ID 创建数据框
Create Dataframe out of distances and id's between dataframes
我将尝试解释我目前正在使用的东西:
我有两个数据框:一个用于加油站 A(165 个站点),另一个用于加油站 B(257 个站点)。它们都具有相同的格式:
id Coor
1 (a1,b1)
2 (a2,b2)
Coor 具有包含位置坐标的元组。我想要做的是将 3 列添加到 Dataframe A,最近的竞争对手#1、#2 和#3(来自加油站 B)。
目前我设法获得了从 A 到 B 的所有距离(42405 个距离度量),但采用列表格式:
distances=[]
for (u,v) in gasA['coor']:
for (w,x) in gasB['coor']:
distances.append(sp.distance.euclidean((u,v),(w,x)))
这让我得到了我需要的值,但我仍然需要将它们与加油站 A 的 ID 进行匹配,并获得前 3 名。我怀疑使用列表不是这里的最佳方法。你有什么建议吗?
编辑:按照建议,前 5 行是:
在 GasA 中:
id coor
60712 (-333525363206695,-705191013427772)
60512 (-333539879388388, -705394161580837)
60085 (-333545609177068, -703168832659184)
60110 (-333601677229216, -705167284798638)
60078 (-333608898397271, -707213099595404)
在 GasB 中:
id coor
70174 (-333427160000000,-705459060000000)
70223 (-333523030000000, -706705470000000)
70383 (-333549270000000, -705320990000000)
70162 (-333556960000000, -705384750000000)
70289 (-333565850000000, -705104360000000)
你可以这样做。
a = gasA.coor.values
b = gasB.coor.values
c = np.sum(np.sum((a[:,None,::-1] - b)**2, axis=1), axis=0)
我们可以获得两者坐标的 numpy 数组,然后广播 a 来表示它的所有组合,然后采用欧氏距离。
定义一个函数,用于计算从 A 到所有 B 的距离以及具有三个最小距离的 B 的 returns 索引。
def get_nearest_three(row):
(u,v) = row['Coor']
dist_list = gasB.Coor.apply(sp.distance.euclidean,args = [u,v])
# want indices of the 3 indices of B with smallest distances
return list(np.argsort(dist_list))[0:3]
gasA['dists'] = gasA.apply(get_nearest_three, axis = 1)
考虑一个交叉连接(匹配两个数据集之间的每一行每一行),这应该可以用你的小集合管理,165 X 257,然后计算距离。然后,按距离排序,筛选出前 3 名。
cj_df = pd.merge(gasA.assign(key=1), gasB.assign(key=1),
on="key", suffixes=['_A', '_B'])
cj_df['distance'] = cj_df.apply(lambda row: sp.distance.euclidean(row['Coor_A'],
row['Coor_B']),
axis = 1)
# RANK BY DISTANCE
cj_df['rank'] = .groupby('id_A')['distance'].rank()
# FILTER FOR TOP 3
top3_df = cj_df[cj_df['rank'] <= 3].sort_values(['id_A', 'rank'])
from sklearn.metrics.pairwise import euclidean_distances
import numpy as np
正在创建数据:
A = pd.DataFrame({'id':['60712','60512','60085', '60110','60078'], 'coor':[ (-333525363206695,-705191013427772),\
(-333539879388388, -705394161580837),\
(-333545609177068, -703168832659184),\
(-333601677229216, -705167284798638),\
(-333608898397271, -707213099595404)]})
B = pd.DataFrame({'id':['70174','70223','70383', '70162','70289'], 'coor':[ (-333427160000000,-705459060000000),\
(-333523030000000, -706705470000000),\
(-333549270000000, -705320990000000),\
(-333556960000000, -705384750000000),\
(-333565850000000, -705104360000000)]})
正在计算距离:
res = euclidean_distances(list(A.coor), list(B.coor))
从 B 中选择前 3 个最近的站点并附加到 A 中的列:
d = []
for i, id_ in enumerate(A.index):
distances = np.argsort(res[i])[0:3] #select top 3
distances = B.iloc[distances]['id'].values
d.append(distances)
A = A.assign(dist=d)
编辑
运行 示例的结果:
coor id dist
0 (-333525363206695, -705191013427772) 60712 [70223, 70174, 70162]
1 (-333539879388388, -705394161580837) 60512 [70223, 70289, 70174]
2 (-333545609177068, -703168832659184) 60085 [70223, 70174, 70162]
3 (-333601677229216, -705167284798638) 60110 [70223, 70174, 70162]
4 (-333608898397271, -707213099595404) 60078 [70289, 70383, 70162]
我将尝试解释我目前正在使用的东西: 我有两个数据框:一个用于加油站 A(165 个站点),另一个用于加油站 B(257 个站点)。它们都具有相同的格式:
id Coor
1 (a1,b1)
2 (a2,b2)
Coor 具有包含位置坐标的元组。我想要做的是将 3 列添加到 Dataframe A,最近的竞争对手#1、#2 和#3(来自加油站 B)。 目前我设法获得了从 A 到 B 的所有距离(42405 个距离度量),但采用列表格式:
distances=[]
for (u,v) in gasA['coor']:
for (w,x) in gasB['coor']:
distances.append(sp.distance.euclidean((u,v),(w,x)))
这让我得到了我需要的值,但我仍然需要将它们与加油站 A 的 ID 进行匹配,并获得前 3 名。我怀疑使用列表不是这里的最佳方法。你有什么建议吗?
编辑:按照建议,前 5 行是: 在 GasA 中:
id coor
60712 (-333525363206695,-705191013427772)
60512 (-333539879388388, -705394161580837)
60085 (-333545609177068, -703168832659184)
60110 (-333601677229216, -705167284798638)
60078 (-333608898397271, -707213099595404)
在 GasB 中:
id coor
70174 (-333427160000000,-705459060000000)
70223 (-333523030000000, -706705470000000)
70383 (-333549270000000, -705320990000000)
70162 (-333556960000000, -705384750000000)
70289 (-333565850000000, -705104360000000)
你可以这样做。
a = gasA.coor.values
b = gasB.coor.values
c = np.sum(np.sum((a[:,None,::-1] - b)**2, axis=1), axis=0)
我们可以获得两者坐标的 numpy 数组,然后广播 a 来表示它的所有组合,然后采用欧氏距离。
定义一个函数,用于计算从 A 到所有 B 的距离以及具有三个最小距离的 B 的 returns 索引。
def get_nearest_three(row):
(u,v) = row['Coor']
dist_list = gasB.Coor.apply(sp.distance.euclidean,args = [u,v])
# want indices of the 3 indices of B with smallest distances
return list(np.argsort(dist_list))[0:3]
gasA['dists'] = gasA.apply(get_nearest_three, axis = 1)
考虑一个交叉连接(匹配两个数据集之间的每一行每一行),这应该可以用你的小集合管理,165 X 257,然后计算距离。然后,按距离排序,筛选出前 3 名。
cj_df = pd.merge(gasA.assign(key=1), gasB.assign(key=1),
on="key", suffixes=['_A', '_B'])
cj_df['distance'] = cj_df.apply(lambda row: sp.distance.euclidean(row['Coor_A'],
row['Coor_B']),
axis = 1)
# RANK BY DISTANCE
cj_df['rank'] = .groupby('id_A')['distance'].rank()
# FILTER FOR TOP 3
top3_df = cj_df[cj_df['rank'] <= 3].sort_values(['id_A', 'rank'])
from sklearn.metrics.pairwise import euclidean_distances
import numpy as np
正在创建数据:
A = pd.DataFrame({'id':['60712','60512','60085', '60110','60078'], 'coor':[ (-333525363206695,-705191013427772),\
(-333539879388388, -705394161580837),\
(-333545609177068, -703168832659184),\
(-333601677229216, -705167284798638),\
(-333608898397271, -707213099595404)]})
B = pd.DataFrame({'id':['70174','70223','70383', '70162','70289'], 'coor':[ (-333427160000000,-705459060000000),\
(-333523030000000, -706705470000000),\
(-333549270000000, -705320990000000),\
(-333556960000000, -705384750000000),\
(-333565850000000, -705104360000000)]})
正在计算距离:
res = euclidean_distances(list(A.coor), list(B.coor))
从 B 中选择前 3 个最近的站点并附加到 A 中的列:
d = []
for i, id_ in enumerate(A.index):
distances = np.argsort(res[i])[0:3] #select top 3
distances = B.iloc[distances]['id'].values
d.append(distances)
A = A.assign(dist=d)
编辑
运行 示例的结果:
coor id dist
0 (-333525363206695, -705191013427772) 60712 [70223, 70174, 70162]
1 (-333539879388388, -705394161580837) 60512 [70223, 70289, 70174]
2 (-333545609177068, -703168832659184) 60085 [70223, 70174, 70162]
3 (-333601677229216, -705167284798638) 60110 [70223, 70174, 70162]
4 (-333608898397271, -707213099595404) 60078 [70289, 70383, 70162]