Как передать столбцы в двух фреймах данных в функцию гаверсина?

Я новичок в долгих и долгих вещах. Я нашел функцию Хаверсина, которая выглядит интересной. У меня есть два фрейма данных, которые я пытаюсь передать в функцию, но получаю сообщение об ошибке.

Вот функция.

import numpy as np

lon1 = df["longitude_fuze"]
lat1 = df["latitude_fuze"]
lon2 = df["longitude_air"]
lat2 = df["latitude_air"]

# Haversine
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    km = 6367 * c
    return km

Я пытаюсь добавить это в столбец во фрейме данных, вот так.

df['haversine_dist'] = haversine(lon1,lat1,lon2,lat2)

Функция компилируется нормально, но когда я пытаюсь ее вызвать, я получаю эту ошибку.

df['haversine_dist'] = haversine(lon1,lat1,lon2,lat2)
Traceback (most recent call last):

  File "<ipython-input-38-cc7e470610ee>", line 1, in <module>
    df['haversine_dist'] = haversine(lon1,lat1,lon2,lat2)

  File "<ipython-input-37-f357b0fc2e88>", line 16, in haversine
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

  File "C:\Users\ryans\anaconda3\lib\site-packages\pandas\core\series.py", line 129, in wrapper
    raise TypeError(f"cannot convert the series to {converter}")

TypeError: cannot convert the series to <class 'float'>

Вот два фрейма данных, которые я тестирую.

# Import pandas library 
import pandas as pd 
  
# initialize list of lists 
data = [['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'], 
        ['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'],
        ['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'],
        ['NY', 'NY', 'New York', '40.76', '73.98'],
        ['NY', 'NY', 'New York', '40.76', '73.98']] 
  
# Create the pandas DataFrame 
df_result = pd.DataFrame(data, columns = ['state', 'city', 'county','latitude_fuze','longitude_fuze']) 
# print dataframe. 
df_result


data = [['New York', 'JFK', '40.63', '-73.60'], 
        ['New York', 'JFK', '40.64', '-73.78'],
        ['Los Angeles', 'LAX', '33.94', '-118.41'],
        ['Chicago', 'ORD', '40.98', '73.90'],
        ['San Francisco', 'SFO', '40.62', '73.38']] 
  
# Create the pandas DataFrame 
df_airports = pd.DataFrame(data, columns = ['municipality_name', 'airport_code', 'latitude_air','longitude_air']) 
# print dataframe. 
df_airports

Я нашел функцию по этой ссылке.

См. также:  Julia Box: Google Colab для Джулии

https://kanoki.org/2019/12/27/how-to-calculate-distance-in-python-and-pandas-using-scipy-spatial-and-distance-functions/

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. ASH

    Я вижу здесь две проблемы:

    1. Долгота и широта по-прежнему являются строками во фреймах данных, поэтому вы, вероятно, столкнетесь с проблемами с типами данных.

    2. Используемая здесь реализация haversine не работает из коробки с объектами, подобными массивам, для долготы и широты.


    Проблема с типом данных может быть легко решена с помощью astype. Например, вы можете использовать lon1 = df["longitude_fuze"].astype(float). Или, что еще лучше, измените тип прямо во фрейме данных:

    dt_dict = {"longitude_fuze": float, "latitude_fuze": float, 
               "longitude_air": float, "latitude_air": float}
    df = df.astype(dt_dict)
    

    Для функции hoversine, поддерживающей аргументы, подобные массиву, поскольку она довольно проста, я бы предложил повторно реализовать ее, чтобы она была совместима с numpy. Я пошел дальше и сделал это за вас:

    import numpy as np
    
    def haversine_array(lon1, lat1, lon2, lat2):
        """
        Calculate the great circle distance between two points 
        on the earth (specified in decimal degrees)
        """
        # convert decimal degrees to radians 
        lon1, lat1, lon2, lat2 = map(lambda x: x/360.*(2*np.pi), [lon1, lat1, lon2, lat2])
        # haversine formula 
        dlon = lon2 - lon1 
        dlat = lat2 - lat1 
        a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
        c = 2 * np.arcsin(np.sqrt(a)) 
        km = 6367 * c
        return km
    
    

    Собираем вместе:

    import pandas as pd
    import numpy as np
    
    def haversine_array(lon1, lat1, lon2, lat2):
        """
        Calculate the great circle distance between two points 
        on the earth (specified in decimal degrees)
        """
        # convert decimal degrees to radians 
        lon1, lat1, lon2, lat2 = map(lambda x: x/360.*(2*np.pi), [lon1, lat1, lon2, lat2])
        # haversine formula 
        dlon = lon2 - lon1 
        dlat = lat2 - lat1 
        a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
        c = 2 * np.arcsin(np.sqrt(a)) 
        km = 6367 * c
        return km
    
    # initialize list of lists 
    data = [['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'], 
            ['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'],
            ['NY', 'Uniondale', 'Nassau', '40.72', '-73.59'],
            ['NY', 'NY', 'New York', '40.76', '73.98'],
            ['NY', 'NY', 'New York', '40.76', '73.98']] 
      
    # Create the pandas DataFrame 
    df_result = pd.DataFrame(data, columns = ['state', 'city', 'county','latitude_fuze','longitude_fuze']) 
    data = [['New York', 'JFK', '40.63', '-73.60'], 
            ['New York', 'JFK', '40.64', '-73.78'],
            ['Los Angeles', 'LAX', '33.94', '-118.41'],
            ['Chicago', 'ORD', '40.98', '73.90'],
            ['San Francisco', 'SFO', '40.62', '73.38']]
    df_airports = pd.DataFrame(data, columns = ['municipality_name', 'airport_code', 'latitude_air','longitude_air'])
    
    # note the conversion to float
    
    lon1 = df_result["longitude_fuze"].astype(float)
    lat1 = df_result["latitude_fuze"].astype(float)
    lon1 = df_result["longitude_fuze"].astype(float)
    lon2 = df_airports['longitude_air'].astype(float)
    lat2 = df_airports['latitude_air'].astype(float)
    
    # using the haversine implementation above
    
    df_result['haversine_dist'] = haversine_array(lon1, lat1, lon2, lat2)
    
    

    Теперь вы получите:

    >>> df_result['haversine_dist']
    0      10.036708
    1      18.314266
    2    3987.270064
    3      25.354970
    4      52.895712
    Name: haversine_dist, dtype: float64
    

    Надеюсь, это помогло!

    Спасибо, но когда я запустил это, я увидел, что все результаты haversine одинаковы; все 52.895712. Похоже, что это цикл, но для расчета используется только последний элемент. Что мне здесь не хватает? person ASH; 21.02.2021

    Я обновил ответ и переименовал numpy-реализацию функции haversine. Надеюсь, теперь это работает и для вас. person ASH; 21.02.2021

    Да, это прекрасно работает! Проверял на этом сайте. movable-type.co.uk/scripts/latlong.html person ASH; 21.02.2021

  2. ASH

    Это потому, что вы передаете данные серии, вместо этого вам нужно передавать одиночные значения.

    # Below variables are going to have series data
    lon1 = df["longitude_fuze"]
    lat1 = df["latitude_fuze"]
    lon2 = df["longitude_air"]
    lat2 = df["latitude_air"]
    

    Вместо этого вы можете выбрать значение по определенному индексу, например, значение по индексу 0:

    lon1 = df["longitude_fuze"].iloc[0]
    lat1 = df["latitude_fuze"].iloc[0]
    lon2 = df["longitude_air"].iloc[0]
    lat2 = df["latitude_air"].iloc[0]
    

    С этими значениями теперь вы можете вызвать свою функцию:

    df['haversine_dist'] = haversine(lon1,lat1,lon2,lat2)
    

    Или вы даже можете сделать это в цикле, если хотите оценить значения для всех значений в этих столбцах:

    for i in df.index:
        lon1 = df["longitude_fuze"].iloc[i]
        lat1 = df["latitude_fuze"].iloc[i]
        lon2 = df["longitude_air"].iloc[i]
        lat2 = df["latitude_air"].iloc[i]
    
        df.loc[i, 'haversine_dist'] = haversine(lon1,lat1,lon2,lat2)
    

    Когда я запускаю это, все строки в df [‘haversine_dist’] имеют одинаковый номер; все 52.895712. Логика кажется правильной, окончательное решение не имеет никакого смысла. Он выполняет расчет только для последнего элемента в индексе. person ASH; 21.02.2021

    Убедитесь, что вызов функции находится внутри цикла, я думаю, вы делаете это вне цикла person ASH; 21.02.2021

    Также была небольшая ошибка, я исправил это person ASH; 21.02.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: