Почему у меня возникает ошибка, когда глобальное имя определено?

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

Это пример моих данных

    ID  timestamp           latitude        longitude
0   72  20/01/2015 09:47    -6.646405565    71.35696828
1   72  20/01/2015 15:47    -6.642237759    71.36032005
2   72  20/01/2015 21:47    -6.639229675    71.36914769
3   73  21/01/2015 03:47    -6.648699053    71.37865551
4   73  21/01/2015 09:47    -6.65574147     71.37957366
5   74  21/01/2015 15:47    -6.660118996    71.37990588
6   74  21/01/2015 21:47    -6.666138734    71.38266541

До сих пор мне удалось запустить следующий код

import pandas as pd
df = pd.read_csv(filename)  

df['timestamp'] = pd.to_datetime(df['timestamp'], format='%d/%m/%Y %H:%M')

from math import sin, cos, sqrt, atan2, radians

def getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2):
    R = 6371 # Radius of the earth in km
    dLat = radians(lat2-lat1)
    dLon = radians(lon2-lon1)
    rLat1 = radians(lat1)
    rLat2 = radians(lat2)
    a = sin(dLat/2) * sin(dLat/2) + cos(rLat1) * cos(rLat2) * sin(dLon/2) * sin(dLon/2) 
    c = 2 * atan2(sqrt(a), sqrt(1-a))
    d = R * c # Distance in km
    return d

def calc_velocity(dist_km, time_start, time_end):
    """Return 0 if time_start == time_end, avoid dividing by 0"""
    return dist_km / (time_end - time_start).seconds if time_end > time_start else 0

# First sort by ID and timestamp:
df = df.sort_values(by=['ID', 'timestamp'])

# Group the sorted dataframe by ID, and grab the initial value for lat, lon, and time.
df['lat0'] = df.groupby('ID')['latitude'].transform(lambda x: x.iat[0])
df['lon0'] = df.groupby('ID')['longitude'].transform(lambda x: x.iat[0])
df['t0'] = df.groupby('ID')['timestamp'].transform(lambda x: x.iat[0])

# create a new column for distance
df['dist_km'] = df.apply(
    lambda row: getDistanceFromLatLonInKm(
        lat1=row['latitude'],
        lon1=row['longitude'],
        lat2=row['lat0'],
        lon2=row['lon0']
    ),
    axis=1
)

В этот момент я получаю сообщение об ошибке, которое подразумевает, что 'getDistanceFromLatLonInKm' не был определен, хотя он был. Ниже приведена трассировка и ошибка

Traceback (most recent call last):
  File "<pyshell#36>", line 9, in <module>
    axis=1
  File "C:\Python27\ArcGIS10.6\lib\site-packages\pandas\core\frame.py", line 4061, in apply
    return self._apply_standard(f, axis, reduce=reduce)
  File "C:\Python27\ArcGIS10.6\lib\site-packages\pandas\core\frame.py", line 4157, in _apply_standard
    results[i] = func(v)
  File "<pyshell#36>", line 3, in <lambda>
    lambda row: getDistanceFromLatLonInKm(
NameError: ("global name 'getDistanceFromLatLonInKm' is not defined", u'occurred at index 0')

Где я ошибаюсь в этом коде?


person Jo Harris    schedule 12.03.2019    source источник
comment
пожалуйста, опубликуйте полную трассировку вашей ошибки   -  person Nihal    schedule 12.03.2019
comment
Мои извинения, я обновил свой вопрос, чтобы включить.   -  person Jo Harris    schedule 12.03.2019
comment
вы должны сохранить свой код в файле и запустить его.   -  person Nihal    schedule 12.03.2019
comment
Я вижу pyshell в трассировке стека. Можете ли вы поместить все в скрипт Python и запустить его как «python ‹script_name.py›»? Я смог запустить ваш код без каких-либо ошибок, используя CSV-файл из вопроса, который вы связали.   -  person Manoj Mohan    schedule 12.03.2019
comment
@Manoj Mohan Как я признался в комментарии ниже, я раньше не использовал python, поэтому не уверен, что вы имеете в виду. Я знаю, что это не обслуживание рук, поэтому я скажу спасибо и попробую разобраться. Хорошо знать, что код работает, и только мне нужно научиться его использовать.   -  person Jo Harris    schedule 12.03.2019
comment
Я создал ответ с кодом и шагами, которые нужно выполнить. Пожалуйста, проверьте.   -  person Manoj Mohan    schedule 12.03.2019


Ответы (1)


Пожалуйста, проверьте эту ссылку, если вам нужны некоторые сведения о различных способах выполнения кода Python. https://realpython.com/run-python-scripts/

Скопируйте приведенный ниже код в файл и сохраните его как lat_long.py. Измените только имя CSV-файла «lat_long.csv» в соответствии с вашей системой. Из оболочки или командной строки выполните команду:

python lat_long.py.

Интерпретатор Python запустит содержимое файла lat_long.py и распечатает результаты, если они есть.

import pandas as pd
from math import sin, cos, sqrt, atan2, radians

filename = 'lat_long.csv'
df = pd.read_csv(filename)


df['timestamp'] = pd.to_datetime(df['timestamp'], format='%d/%m/%Y %H:%M')


def getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2):
    R = 6371 # Radius of the earth in km
    dLat = radians(lat2-lat1)
    dLon = radians(lon2-lon1)
    rLat1 = radians(lat1)
    rLat2 = radians(lat2)
    a = sin(dLat/2) * sin(dLat/2) + cos(rLat1) * cos(rLat2) * sin(dLon/2) * sin(dLon/2)
    c = 2 * atan2(sqrt(a), sqrt(1-a))
    d = R * c # Distance in km
    return d

def calc_velocity(dist_km, time_start, time_end):
    """Return 0 if time_start == time_end, avoid dividing by 0"""
    return dist_km / (time_end - time_start).seconds if time_end > time_start else 0

# First sort by ID and timestamp:
df = df.sort_values(by=['ID', 'timestamp'])

# Group the sorted dataframe by ID, and grab the initial value for lat, lon, and time.
df['lat0'] = df.groupby('ID')['latitude'].transform(lambda x: x.iat[0])
df['lon0'] = df.groupby('ID')['longitude'].transform(lambda x: x.iat[0])
df['t0'] = df.groupby('ID')['timestamp'].transform(lambda x: x.iat[0])

# create a new column for distance
df['dist_km'] = df.apply(
    lambda row: getDistanceFromLatLonInKm(
        lat1=row['latitude'],
        lon1=row['longitude'],
        lat2=row['lat0'],
        lon2=row['lon0']
    ),
    axis=1
)
print(df)
person Manoj Mohan    schedule 12.03.2019
comment
Абсолютный гений! Большое спасибо за то, что приложили все усилия, чтобы помочь мне. - person Jo Harris; 12.03.2019