У меня есть кадр данных с идентификатором, широтой и долготой:
ID Latitude Longitude coords
A 45.0353 52.5362 (45.0353, 52.5362)
B 24.6374 12.5363 (24.6374, 12.5363)
C 42.3539 21.O530 (42.3539, 21.O530)
D 48.3638 18.3903 (48.3638, 18.3903)
И мне нужно для каждого из них найти ближайший, а расстояние будет пятым столбцом в нужном кадре данных. Я пытаюсь с:
dicts1 = dict(zip(df.ID, df.coords))
dicts2 = dict(zip(df.ID, df.coords))
f_dict={}
for key, value in dicts1.iteritems():
for k, v in dicts2.iteritems():
lista.append(geopy.distance.vincenty(value, v).km)
f_dict.update({key:lista})
У меня есть только одно расстояние для всех из них, но в данный момент мне нужно получить len(data['ID']) число значений для каждого из них, и это около 1500, поэтому 1500 * 1500, после этого мне нужно чтобы взять ближайшее, наименьшее расстояние (кроме 0). Итак, что-то не так, и я не могу понять, как решить проблему.
Ответ 1 · VMatić
Ваш код не показывает, как определяется lista. Если вы поместите lista=[] в начало внешнего цикла for, он даст вам набор значений 1500 * 1500, который вы ищете. Однако обратите внимание, что вам не нужно определять словари дважды; скорее вы можете перебирать один и тот же словарь дважды. Кроме того, вы можете обновить f_dict после завершения внутреннего цикла, а не обновлять его в каждой итерации:
dicts = dict(zip(df.ID, df.coords))
f_dict={}
for key, value in dicts.iteritems():
lista = []
for k, v in dicts.iteritems():
lista.append(geopy.distance.vincenty(value, v).km)
f_dict.update({key:lista})
Затем вам придется перебрать f_dict, чтобы получить желаемые минимумы.
Однако обратите внимание, что вычисление географических расстояний может быть медленным в вычислительном отношении, поэтому вы можете попробовать игнорировать повторяющиеся пары. То есть, если вы уже сделали A и B, то вам не нужно вычислять его для B и A. Вот версия кода, которая позволяет избежать дублирования вычислений и напрямую возвращает словарь с минимальными расстояниями:
dicts = dict(zip(df.ID, df.coords))
f_dict={}
def update_distances(keys, distance):
for k in keys:
try:
if distance < f_dict[k]:
f_dict.update({k:distance})
except KeyError:
f_dict.update({k:distance})
for idx1, (key, value) in enumerate(dicts.iteritems()):
for idx2, (k, v) in enumerate(dicts.iteritems()):
if idx2 <= idx1:
continue # Skip a repeated calculation of distance
update_distances([key, k], geopy.distance.vincenty(value, v).km)