Найдите ближайшую точку для каждой точки в кадре данных

У меня есть кадр данных с идентификатором, широтой и долготой:

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). Итак, что-то не так, и я не могу понять, как решить проблему.


person jovicbg    schedule 24.11.2017    source источник


Ответы (1)


Ваш код не показывает, как определяется 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)
person VMatić    schedule 24.11.2017