Добавление расстояний, покрываемых идентификаторами, и добавление этого значения в столбец фрейма данных pandas

#python #pandas #numpy #scipy

#питон #панды #numpy #scipy

Вопрос:

Фрейм grouped данных имеет следующее описание:

  1. ПОЛЬЗОВАТЕЛЬ: представляет пользователя;
  2. ПРЕДПОЛАГАЕМАЯ РЕЗИДЕНТНОСТЬ: антенна, ближайшая к месту жительства пользователя;
  3. CALL_LOC: антенна, ближайшая к месту, где пользователь совершил вызов.

фрейм данных grouped :

 import pandas as pd
import numpy as np
from math import sin, cos, sqrt, atan2, radians
from scipy.spatial.distance import pdist, squareform

df = pd.DataFrame({'USER':[1,2,3,1,1,2],
                   'ANTENNA_ID': ['SJDR1', 'LD1', 'LD1', 'LD', 'TR', 'SVM']})


df2 = pd.DataFrame({'USER': [1,2,3,4,5],
                    'PRESUMED_RESIDENCE': ['SJDR1', 'LD1', 'LD1', 'TR', 'SVM']})

merged = pd.merge(df, df2, left_on='USER', right_on='USER')

grouped = merged.groupby('USER').agg({'PRESUMED_RESIDENCE': min, 'ANTENNA_ID':list}).reset_index()

grouped['ANTENNA_ID'] = [[z for z in x if z!=y]
                         for x,y in zip(grouped['ANTENNA_ID'],
                                       grouped['PRESUMED_RESIDENCE'])]

grouped = grouped.rename(columns={'ANTENNA_ID': 'CALL_LOC'})
 

Фрейм antennas_loc данных содержит пару кординат для каждой антенны:

 antennas_loc = pd.DataFrame({'ANTENNA_ID': ['SJDR1', 'LD1', 'LD2', 'TR', 'SVM'],'LAT': [-22.98, -22.97, -22.92, -22.87, -22.89], 'LONG': [-43.19, -43.39, -43.24, -43.28, -43.67]})
antennas_loc
 

Ниже я использовал dist функцию для вычисления расстояния между антеннами:

 def dist(x, y):
    
    lat1 = radians(x[0])
    lon1 = radians(x[1])
    lat2 = radians(y[0])
    lon2 = radians(y[1])
    
    R = 6373.0
    
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    
    a = sin(dlat/2) ** 2   cos(lat1) * cos(lat2) * sin(dlon/2) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))
    
    distance = R * c
    
    return round(distance, 4)

distances = pdist(antennas_loc[['LAT', 'LONG']].values, metric=dist)

points = antennas_loc['ANTENNA_ID'].values

result = pd.DataFrame(squareform(distances), columns=points, index=points)

result
 

Что мне нужно сделать сейчас, так это создать столбец в сгруппированном фрейме данных, который представляет расстояние, пройденное пользователем, на основе его PRESUMED_RESIDENCE . Взяв пользователя 1 в качестве примера, вычисление будет следующим:

  1. PRESUMED_RESIDENCE : SJDR1
  2. CALL_LOC : [LD2, TR]
  3. Пройденное расстояние: (расстояние между SJDR1 и LD2) (расстояние между SJDR1 и TR).

Строка для пользователя 1 будет выглядеть следующим образом:

 USER | PRESUMED_RESIDENCE | CALL_LOC | TRAVELLED_DISTANCE
 1   |       SJDR1        | [LD2, TR]|      23,7326  
 

Однако я понятия не имею, как я могу просмотреть результат фрейма данных, выполнить поиск координат места жительства и вычислить расстояние от этой точки до мест соединения. Кто-нибудь может помочь?

Ответ №1:

Я предполагаю, что ваш первый фрейм данных на самом деле:

 df = pd.DataFrame({'USER':[1,2,3,1,1,2],
                   'ANTENNA_ID': ['SJDR1', 'LD1', 'LD1', 'LD2', 'TR', 'SVM']})
 

Тогда это должно сработать:

 from math import sin, cos, sqrt, atan2, radians
from scipy.spatial.distance import pdist, squareform

df = pd.DataFrame({'USER': [1,2,3,1,1,2],
                   'ANTENNA_ID': ['SJDR1', 'LD1', 'LD1', 'LD2', 'TR', 'SVM']})

df2 = pd.DataFrame({'USER': [1,2,3,4,5],
                    'PRESUMED_RESIDENCE': ['SJDR1', 'LD1', 'LD1', 'TR', 'SVM']})

merged = pd.merge(df, df2, left_on='USER', right_on='USER')
merged = merged[merged['ANTENNA_ID'] != merged['PRESUMED_RESIDENCE']]

antennas_loc = pd.DataFrame({'ANTENNA_ID': ['SJDR1', 'LD1', 'LD2', 'TR', 'SVM'],
                             'LAT': [-22.98, -22.97, -22.92, -22.87, -22.89],
                             'LONG': [-43.19, -43.39, -43.24, -43.28, -43.67]})

def dist(x, y):
    lat1 = radians(x[0])
    lon1 = radians(x[1])
    lat2 = radians(y[0])
    lon2 = radians(y[1])

    R = 6373.0

    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = sin(dlat / 2) ** 2   cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))

    distance = R * c

    return round(distance, 4)

distances = pdist(antennas_loc[['LAT', 'LONG']].values, metric=dist)

points = antennas_loc['ANTENNA_ID'].values

result = pd.DataFrame(squareform(distances), columns=points, index=points)
melt_df = pd.melt(result.reset_index(), id_vars='index')
melt_df.rename(columns={'index': 'ANTENNA_ID', 'variable': 'PRESUMED_RESIDENCE', 'value': 'DISTANCE'}, inplace=True)

df_main = pd.merge(merged, melt_df, left_on=['ANTENNA_ID', 'PRESUMED_RESIDENCE'], right_on=['ANTENNA_ID', 'PRESUMED_RESIDENCE'])

df_final = df_main.groupby(['USER', 'PRESUMED_RESIDENCE']).agg({'ANTENNA_ID': list, 'DISTANCE': sum}).reset_index()
df_final.rename(columns={'ANTENNA_ID':'CALL_LOC', 'DISTANCE': 'TRAVELLED_DISTANCE'}, inplace=True)

print(df_final)