Гаверсинус Расстояние между последовательными строками для каждого клиента

Мой вопрос основан на этом Fast Haversine Approximation (Python/Pandas)

По сути, этот вопрос спрашивает, как вычислить расстояние гаверсуса. Мой вопрос заключается в том, как рассчитать гаверсинусное расстояние между последовательными строками для каждого клиента.

Мой набор данных выглядит примерно как этот фиктивный (предположим, что это настоящие координаты):

  Customer  Lat Lon
    A        1  2
    A        1  2
    B        3  2
    B        4  2

Итак, здесь я ничего не получил бы в первой строке, 0 во второй строке, снова ничего в третьей, потому что новый клиент начал и независимо от расстояния в км между (3,2) и (4,2) в четвертом .

Это работает без ограничений клиентов:

def haversine(lat1, lon1, lat2, lon2, to_radians=True):
    if to_radians:
        lat1, lon1, lat2, lon2 = np.radians([lat1, lon1, lat2, lon2])

    a = np.sin((lat2-lat1)/2.0)**2 + \
        np.cos(lat1) * np.cos(lat2) * np.sin((lon2-lon1)/2.0)**2

    return 6367 * 2 * np.arcsin(np.sqrt(a))

df=data_full
df['dist'] = \
    haversine(df.Lon.shift(), df.Lat.shift(),
             df.loc[1:, 'Lon'], df.loc[1:, 'Lat'])

Но я не могу настроить его для перезапуска с каждым новым клиентом. Я пробовал это:

 def haversine(lat1, lon1, lat2, lon2, to_radians=True):
    if to_radians:
        lat1, lon1, lat2, lon2 = np.radians([lat1, lon1, lat2, lon2])

    a = np.sin((lat2-lat1)/2.0)**2 + \
        np.cos(lat1) * np.cos(lat2) * np.sin((lon2-lon1)/2.0)**2

    return 6367 * 2 * np.arcsin(np.sqrt(a))

df=data_full
df['dist'] = \
    df.groupby('Customer_id')['Lat','Lon'].apply(lambda df: haversine(df.Lon.shift(), df.Lat.shift(),
             df.loc[1:, 'Lon'], df.loc[1:, 'Lat']))

person Nocas    schedule 20.08.2019    source источник
comment
В чем проблема?   -  person ifly6    schedule 20.08.2019


Ответы (1)


Я буду повторно использовать векторизованную функцию haversine_np из ответа derricw:

def haversine_np(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)

    All args must be of equal length.    

    """
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2

    c = 2 * np.arcsin(np.sqrt(a))
    km = 6367 * c
    return km

def distance(x):
    y = x.shift()
    return haversine_np(x['Lat'], x['Lon'], y['Lat'], y['Lon']).fillna(0)

df['Distance'] = df.groupby('Customer').apply(distance).reset_index(level=0, drop=True)

Результат:

  Customer  Lat  Lon    Distance
0        A    1    2    0.000000
1        A    1    2    0.000000
2        B    3    2    0.000000
3        B    4    2  111.057417
person Code Different    schedule 20.08.2019