#python-3.x #pandas #for-loop #geopy
Вопрос:
Я учусь сам geopy
. Это кажется простым и понятным, но мой код не работает. Предполагается, что:
- прочитайте в списке поля адреса из CSV в
pandas
df - объедините поля адресов в один столбец, отформатированный для
geopy
- составьте список из нового столбца
- введите каждый элемент в списке
geopy
через цикл for и верните координаты добавьте координаты в исходный файл df и экспортируйте его в CSV
#setup
from geopy.geocoders import Nominatim
import pandas as pd
#create the df
df = pd.DataFrame(pd.read_csv('properties to geocode.csv'))
df['Location'] = df['Street Address'].astype(str) "," df['City'].astype(str) "," df['State'].astype(str)
#create the geolocator object
geolocator = Nominatim(timeout=1, user_agent = "My_Agent")
#create the locations list
locations = df['Location']
#empty lists for later columns
lats = []
longs = []
#process the location list
for item in locations:
location = geolocator.geocode('item')
lat = location.latitude
long = location.longitude
lats.append(lat)
longs.append(long)
#add the lists to the df
df.insert(5,'Latitude',lats)
df.insert(6,'Longitude',longs)
#export
df.to_csv('geocoded-properties2.csv',index=False)
Что-то не работает, потому что оно возвращает одинаковые значения широты и долготы для каждой строки вместо уникальных координат для каждой.
Я нашел рабочий код с использованием .apply в другом месте, но мне интересно узнать, что я сделал не так. Есть какие-нибудь мысли?
Комментарии:
1.
location = geolocator.geocode('item')
вы передаете строковый литерал, а не значение элемента переменной2. Спасибо за ваш ответ. когда я удаляю «»вокруг элемента, я получаю следующую ошибку: Ошибка атрибута: объект «Нетип» не имеет атрибута «широта»
3. Я дал более развернутый ответ. Если вы укажете адрес, который не найден
geolocator.geocode()
, возвращаетсяNone
. Это явно проверяется в функции, которую я написал, прежде чем она вернется
Ответ №1:
- ваш код не содержит примеров данных. Использовали некоторые примеры данных, доступных из общедоступных API, для демонстрации
- ваш код передает литерал в
geolocator.geocode()
— это должен быть адрес, связанный со строкой - привели пример использования с пандами
apply
, понимание списка иfor
эквивалент цикла понимания - результаты показывают, что все три подхода эквивалентны
from geopy.geocoders import Nominatim
import requests
import pandas as pd
searchendpoint = "https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations"
# get all healthcare facilities in Herefordshire
dfhc = pd.concat([pd.json_normalize(requests
.get(searchendpoint, params={"PostCode":f"HR{i}","Status":"Active"})
.json()["Organisations"])
for i in range(1,10)]).reset_index(drop=True)
def gps(url, geolocator=None):
# get the address and construct a space delimted string
a = " ".join(str(x) for x in requests.get(url).json()["Organisation"]["GeoLoc"]["Location"].values())
lonlat = geolocator.geocode(a)
if not lonlat is None:
return lonlat[1]
else:
return (0,0)
# work with just GPs
dfgp = dfhc.loc[dfhc.PrimaryRoleId.isin(["RO180","RO96"])].head(5).copy()
geolocator = Nominatim(timeout=1, user_agent = "My_Agent")
# pandas apply
dfgp["lonlat_apply"] = dfgp["OrgLink"].apply(gps, geolocator=geolocator)
# list comprehension
lonlat = [gps(url, geolocator=geolocator) for url in dfgp["OrgLink"].values]
dfgp["lonlat_listcomp"] = lonlat
# old school loop
lonlat = []
for item in dfgp["OrgLink"].values:
lonlat.append(gps(item, geolocator=geolocator))
dfgp["lonlat_oldschool"] = lonlat
Имя | ОргИд | Статус | Класс оргрекордов | почтовый индекс | Дата последнего изменения | Первичная роль | Первичное описание | OrgLink | lonlat_apply | lonlat_listcomp | lonlat_oldschool | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
7 | ОПЕРАЦИЯ НА ЭЙЛСТОУН-ХИЛЛ | M81026002 | Активный | RC2 | 1 ЧАС 1 ЧАС | 2020-03-19 | РО96 | ОТРАСЛЕВАЯ ХИРУРГИЯ | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/M81026002 | (52.0612429, -2.7026047) | (52.0612429, -2.7026047) | (52.0612429, -2.7026047) |
9 | ШКОЛА БАРРС-КОРТ | 5CN91 | Активный | RC2 | HR1 1EQ | 2021-01-28 | RO180 | САЙТ ДОВЕРИЯ ПЕРВИЧНОЙ МЕДИЦИНСКОЙ ПОМОЩИ | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/5CN91 | (52.0619209, -2.7086105) | (52.0619209, -2.7086105) | (52.0619209, -2.7086105) |
13 | ОПЕРАЦИЯ В БОДЕНХЭМЕ | 5CN24 | Активный | RC2 | HR1 3JU | 2013-05-08 | RO180 | САЙТ ДОВЕРИЯ ПЕРВИЧНОЙ МЕДИЦИНСКОЙ ПОМОЩИ | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/5CN24 | (52.152405, -2.6671942) | (52.152405, -2.6671942) | (52.152405, -2.6671942) |
22 | АББАТСТВО БЕЛЬМОНТ | 5CN16 | Активный | RC2 | HR2 9RP | 2013-05-08 | RO180 | САЙТ ДОВЕРИЯ ПЕРВИЧНОЙ МЕДИЦИНСКОЙ ПОМОЩИ | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/5CN16 | (52.0423056, -2.7648698) | (52.0423056, -2.7648698) | (52.0423056, -2.7648698) |
24 | МЕДИЦИНСКИЙ ЦЕНТР БЕЛЬМОНТА | 5CN22 | Активный | RC2 | HR2 7XT | 2013-05-08 | RO180 | САЙТ ДОВЕРИЯ ПЕРВИЧНОЙ МЕДИЦИНСКОЙ ПОМОЩИ | https://directory.spineservices.nhs.uk/ORD/2-0-0/organisations/5CN22 | (52.0407746, -2.739788) | (52.0407746, -2.739788) | (52.0407746, -2.739788) |