Адаптировано с этого ответа.Связанный ответ показывает, как вычислить расстояние между каждой строкой и некоторое фиксированное значение для долготы / широты - моя адаптация позволяет работать в вашем случае.
Во-первых, получите все необходимые значения в одной строке, используя shift
:
df['lon2'] = df['lon'].shift(-1)
df['lat2'] = df['lat'].shift(-1)
Предоставление:
id lat lon lat2 lon2
0 1 NaN NaN 40.121 23.749
1 1 40.121 23.749 -56.154 -39.572
2 1 -56.154 -39.572 21.908 17.537
3 1 21.908 17.537 31.221 -36.186
4 1 31.221 -36.186 -56.655 0.016
5 1 -56.655 0.016 NaN NaN
6 2 NaN NaN -36.438 14.874
7 2 -36.438 14.874 -21.422 81.271
8 2 -21.422 81.271 43.961 -95.551
9 2 43.961 -95.551 NaN NaN
10 3 NaN NaN 79.821 -56.781
11 3 79.821 -56.781 NaN NaN
Затем определите функцию для расчета расстояния:
from numpy import cos, sin, arcsin, sqrt
from math import radians
def haversine(row):
lon1 = row['lon']
lat1 = row['lat']
lon2 = row['lon2']
lat2 = row['lat2']
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * arcsin(sqrt(a))
km = 6367 * c
return km
и примените ее к вашемуданные с использованием apply
:
df['distance'] = df.apply(haversine, axis=1)
Предоставление:
id lat lon lat2 lon2 distance
0 1 NaN NaN 40.121 23.749 NaN
1 1 40.121 23.749 -56.154 -39.572 12237.017692
2 1 -56.154 -39.572 21.908 17.537 10187.684397
3 1 21.908 17.537 31.221 -36.186 5387.540299
4 1 31.221 -36.186 -56.655 0.016 10343.267833
5 1 -56.655 0.016 NaN NaN NaN
6 2 NaN NaN -36.438 14.874 NaN
7 2 -36.438 14.874 -21.422 81.271 6543.302199
8 2 -21.422 81.271 43.961 -95.551 17480.809345
9 2 43.961 -95.551 NaN NaN NaN
10 3 NaN NaN 79.821 -56.781 NaN
11 3 79.821 -56.781 NaN NaN NaN
Как я полагаю, показывает результаты, которые вы ищете (я протестировал первый и егокажется правильным).
Если хотите, вы можете избавиться от двух вторичных столбцов широты / долготы после завершения вычислений:
df.drop(['lat2', 'lon2'], axis=1, inplace=True)
Я должен отметить, что это решение будетне даст вам максимально быстрых расчетов.См. Вторую половину ответа, который я связал, для изучения того, как это можно улучшить, если производительность является главным приоритетом, хотя ее необходимо адаптировать.