【问题标题】:Iterate geolocation over pandas dataframe在熊猫数据框上迭代地理定位
【发布时间】:2017-12-09 00:10:58
【问题描述】:

我有一个包含两列医院名称和地址的数据框,我想遍历每个地址以查找纬度和经度。我的代码似乎占据了数据框中的第一行,我似乎无法选择地址来查找坐标。

import pandas
from geopy.geocoders import Nominatim

geolocator = Nominatim()
for index, item in df.iterrows():
    location = geolocator.geocode(item)
    df["Latitude"].append(location.latitude)
    df["Longitude"].append(location.longitude)

这是我用来抓取网站的代码。复制并运行它,您将拥有数据集。

import requests
from bs4 import BeautifulSoup
import pandas
import numpy as np

r=requests.get("https://www.privatehealth.co.uk/hospitals-and-
clinics/orthopaedic-surgery/?offset=300")
c=r.content
soup=BeautifulSoup(c,"html.parser")
all=soup.find_all(["div"],{"class":"col-9"})
names = []
for item in all:
    d={}
    d["Hospital Name"] = item.find(["h3"],{"class":"mb6"}).text.replace("\n","")
    d["Address"] = item.find(["p"],{"class":"mb6"}).text.replace("\n","")
    names.append(d)
df=pandas.DataFrame(names)
df = df[['Hospital Name','Address']]
df

目前数据如下(以医院为例):

Hospital Name   |Address         
Fulwood Hospital|Preston, PR2 9SZ

我试图实现的最终输出如下所示。

Hospital Name   |Address         | Latitude | Longitude
Fulwood Hospital|Preston, PR2 9SZ|53.7589938|-2.7051618

【问题讨论】:

  • 请提供一些示例数据以及您当前和预期的输出。

标签: python pandas loops geopy


【解决方案1】:

这里似乎有一些问题。使用您提供的 URL 中的数据:

df.head()
                                Hospital Name                   Address
0                        Fortius Clinic City           London, EC4N 7BE
1  Pinehill Hospital - Ramsay Health Care UK           Hitchin, SG4 9QZ
2                  Spire Montefiore Hospital              Hove, BN3 1RD
3             Chelsea & Westminster Hospital           London, SW10 9NH
4   Nuffield Health Tunbridge Wells Hospital   Tunbridge Wells, TN2 4UL

(1) 如果您的数据框列名确实是Hospital nameAddress,那么您需要在对geocode() 的调用中使用item.Address
只需使用item 即可同时获得Hospital nameAddress

for index, item in df.iterrows():
    print(f"index: {index}")
    print(f"item: {item}")
    print(f"item.Address only: {item.Address}")

# Output:
index: 0

item: Hospital Name    Fortius Clinic City 
Address              London, EC4N 7BE
Name: 0, dtype: object

item.Address only: London, EC4N 7BE
...

(2) 您注意到您的数据框只有两列。如果这是真的,当您尝试对df["Latitude"]df["Longitude"] 执行操作时,您将得到一个KeyError,因为它们不存在。

(3)Address 列上使用apply() 可能比iterrows() 更清晰。
请注意,这是一个文体观点,值得商榷。 (前两点是实际错误。)

例如,使用提供的 URL:

from geopy.geocoders import Nominatim
geolocator = Nominatim()

tmp = df.head().copy()

latlon = tmp.Address.apply(lambda addr: geolocator.geocode(addr))

tmp["Latitude"] = [x.latitude for x in latlon]
tmp["Longitude"] = [x.longitude for x in latlon]

输出:

                                Hospital Name                   Address  \
0                        Fortius Clinic City           London, EC4N 7BE   
1  Pinehill Hospital - Ramsay Health Care UK           Hitchin, SG4 9QZ   
2                  Spire Montefiore Hospital              Hove, BN3 1RD   
3             Chelsea & Westminster Hospital           London, SW10 9NH   
4   Nuffield Health Tunbridge Wells Hospital   Tunbridge Wells, TN2 4UL   

    Latitude  Longitude  
0  51.507322  -0.127647  
1  51.946413  -0.279165  
2  50.840871  -0.180561  
3  51.507322  -0.127647  
4  51.131528   0.278068  

【讨论】:

  • 这在一定程度上有效,只要地理编码器不超时并且每秒执行超过 1 个请求。为了解决这个问题,我添加了 time.sleep(2),但我是 lambdas 新手,并意识到多重表达式不是 lambdas 的最佳实践。所以,我正在尝试将 lambda 转换为 for 循环,但遇到了问题。想法??这应该是一个新的 stackoverflow 问题吗?
  • apply 语句中的多步操作最好表示为普通函数而不是 lambda。这与您最初的问题有很大不同,因此我建议您在单独的帖子中提问。但是您可能会发现先尝试构建自己的 UDF 会有所帮助,这个不应该太复杂,并且在 pandas 文档和 SO 中已经有很多关于这个主题的内容可以帮助您。
  • @andrew_reece,很好的解决方案,谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-05-17
  • 2015-12-09
  • 2018-12-03
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多