使用 Google 地图在 R 中进行地理编码

发布于 2024-09-10 05:26:19 字数 1254 浏览 3 评论 0原文

我尝试通过 Google 地图和此博文中的 XML 包运行代码来对 R 中的位置进行地理编码: http://www.r-chart .com/2010/07/maps-geocoding-and-r-user-conference.html

以下是他的函数:

getDocNodeVal=function(doc, path){
  sapply(getNodeSet(doc, path), function(el) xmlValue(el))
}

gGeoCode=function(str){
  library(XML)
  u=paste('http://maps.google.com/maps/api/geocode/xml?sensor=false&address=',str)
  doc = xmlTreeParse(u, useInternal=TRUE)
  str=gsub(' ','%20',str)
  lng=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lat")
  lat=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lng")
  c(lat,lng)
}

当我运行 gGeoCode() 时,出现以下错误:

> gGeoCode("Philadelphia, PA")
failed to load external entity "http%3A//maps.google.com/maps/api/geocode/xml%3Fsensor=false&address=%20Philadelphia,%20PA"
Error: 1: failed to load external entity "http%3A//maps.google.com/maps/api/geocode/xml%3Fsensor=false&address=%20Philadelphia,%20PA"

如果我只需将 API url 粘贴到浏览器中,并在末尾附加 Philadelphia, PA,就像传递给 xmlParseTree 的字符串一样,当我下载它。

这是代码的问题,还是我配置失败?

I've tried running the code to geocode locations in R via Google Maps and the XML package from this blog post:
http://www.r-chart.com/2010/07/maps-geocoding-and-r-user-conference.html

Here are his functions:

getDocNodeVal=function(doc, path){
  sapply(getNodeSet(doc, path), function(el) xmlValue(el))
}

gGeoCode=function(str){
  library(XML)
  u=paste('http://maps.google.com/maps/api/geocode/xml?sensor=false&address=',str)
  doc = xmlTreeParse(u, useInternal=TRUE)
  str=gsub(' ','%20',str)
  lng=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lat")
  lat=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lng")
  c(lat,lng)
}

When I run gGeoCode(), I get the following error:

> gGeoCode("Philadelphia, PA")
failed to load external entity "http%3A//maps.google.com/maps/api/geocode/xml%3Fsensor=false&address=%20Philadelphia,%20PA"
Error: 1: failed to load external entity "http%3A//maps.google.com/maps/api/geocode/xml%3Fsensor=false&address=%20Philadelphia,%20PA"

If I just paste into a browser the API url with Philadelphia, PA appended to the end, like the string passed to xmlParseTree, I get a result that looks like legitimate xml when I download it.

Is this an issue with the code, or have I failed to configure something or another?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

心房敞 2024-09-17 05:26:20

您是否考虑过使用 json 调用来代替?查看您的代码,您可以实现相同的效果(您需要从 omegahat.com 安装软件包 RCurl 和 RJSONIO)。

将其复制并粘贴到 R 中:

library(RCurl)
library(RJSONIO)

construct.geocode.url <- function(address, return.call = "json", sensor = "false") {
  root <- "http://maps.google.com/maps/api/geocode/"
  u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
  return(URLencode(u))
}

gGeoCode <- function(address,verbose=FALSE) {
  if(verbose) cat(address,"\n")
  u <- construct.geocode.url(address)
  doc <- getURL(u)
  x <- fromJSON(doc,simplify = FALSE)
  if(x$status=="OK") {
    lat <- x$results[[1]]$geometry$location$lat
    lng <- x$results[[1]]$geometry$location$lng
    return(c(lat, lng))
  } else {
    return(c(NA,NA))
  }
}

以下是如何使用上述函数:

x <- gGeoCode("Philadelphia, PA")

这是您得到的结果。我认为在原始代码中,lat 和 lng 混淆了?但希望这就是你想要的:

> x
[1]  39.95233 -75.16379

希望对小伙伴有所帮助,

托尼​​·布雷亚尔

Have you thought about using the json call instead? Looking at your code, you could achieve the same doing this (you'll need to install packages RCurl and RJSONIO from omegahat.com).

Copy and paste this into R:

library(RCurl)
library(RJSONIO)

construct.geocode.url <- function(address, return.call = "json", sensor = "false") {
  root <- "http://maps.google.com/maps/api/geocode/"
  u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
  return(URLencode(u))
}

gGeoCode <- function(address,verbose=FALSE) {
  if(verbose) cat(address,"\n")
  u <- construct.geocode.url(address)
  doc <- getURL(u)
  x <- fromJSON(doc,simplify = FALSE)
  if(x$status=="OK") {
    lat <- x$results[[1]]$geometry$location$lat
    lng <- x$results[[1]]$geometry$location$lng
    return(c(lat, lng))
  } else {
    return(c(NA,NA))
  }
}

Here's how you use the above functions:

x <- gGeoCode("Philadelphia, PA")

This is the result you get. I think in the original code, lat and lng are mixed up? But hopefully this is what you want:

> x
[1]  39.95233 -75.16379

Hope that helps a little mate,

Tony Breyal

黑色毁心梦 2024-09-17 05:26:20

此代码仅使用 XML 库即可工作

library(XML)
url = 'http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true'
doc = xmlTreeParse(url, useInternal=TRUE)
lat = as.numeric(xmlValue(getNodeSet(doc, '//location/lat')[[1]]))
lng = as.numeric(xmlValue(getNodeSet(doc, '//location/lng')[[1]]))

This code works using just the XML library

library(XML)
url = 'http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true'
doc = xmlTreeParse(url, useInternal=TRUE)
lat = as.numeric(xmlValue(getNodeSet(doc, '//location/lat')[[1]]))
lng = as.numeric(xmlValue(getNodeSet(doc, '//location/lng')[[1]]))
饭团 2024-09-17 05:26:20

这是地理编码的另一个选项 - 它可能更容易解析:

https://webgis。 usc.edu/Services/Geocode/Default.aspx

This is another option for geocoding - it may be easier to parse:

https://webgis.usc.edu/Services/Geocode/Default.aspx

小帐篷 2024-09-17 05:26:20

我修改了 Tony Breyal 解决方案,以便 gGeoCode 函数也将地址向量作为输入。在此版本中,您不仅可以执行 gGeoCode("Philadelphia, PA") 操作,还可以执行 gGeoCode(c("Philadelphia, PA","New York, NY")) 具有此返回值。

  address            lat          lng          
1 "Philadelphia, PA" "39.952335"  "-75.163789" 
2 "New York, NY"     "40.7143528" "-74.0059731"

请注意,Google 地图 api 的每日限制为 2,500 个,因此您的矢量不应太长。这是更新后的函数:

library(RCurl)
library(RJSONIO)

construct.geocode.url <- function(address, return.call = "json", sensor = "false") {
  root <- "http://maps.google.com/maps/api/geocode/"
  u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
  return(URLencode(u))
}

gGeoCode <- function(address,verbose=FALSE) {
  require("plyr")
  if(verbose) cat(address,"\n")
  u <- aaply(address,1,construct.geocode.url)
  doc <- aaply(u,1,getURL)
  json <- alply(doc,1,fromJSON,simplify = FALSE)
  coord = laply(json,function(x) {
    if(x$status=="OK") {
      lat <- x$results[[1]]$geometry$location$lat
      lng <- x$results[[1]]$geometry$location$lng
      return(c(lat, lng))
    } else {
      return(c(NA,NA))
    }
  })
  if(length(address)>1) colnames(coord)=c("lat","lng")
  else names(coord)=c("lat","lng")
  return(data.frame(address,coord))
}

编辑:代码中的小修正,以便 lat 和 lng 以数值形式返回。

I have modified Tony Breyal solution so that the gGeoCode function also takes a vector of addresses as input. With this version, you can not only do gGeoCode("Philadelphia, PA") but also gGeoCode(c("Philadelphia, PA","New York, NY")) with this return value.

  address            lat          lng          
1 "Philadelphia, PA" "39.952335"  "-75.163789" 
2 "New York, NY"     "40.7143528" "-74.0059731"

Note that the google maps api has a daily limit of 2,500 so that your vector shouldn't be too long. Here is the updated function:

library(RCurl)
library(RJSONIO)

construct.geocode.url <- function(address, return.call = "json", sensor = "false") {
  root <- "http://maps.google.com/maps/api/geocode/"
  u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
  return(URLencode(u))
}

gGeoCode <- function(address,verbose=FALSE) {
  require("plyr")
  if(verbose) cat(address,"\n")
  u <- aaply(address,1,construct.geocode.url)
  doc <- aaply(u,1,getURL)
  json <- alply(doc,1,fromJSON,simplify = FALSE)
  coord = laply(json,function(x) {
    if(x$status=="OK") {
      lat <- x$results[[1]]$geometry$location$lat
      lng <- x$results[[1]]$geometry$location$lng
      return(c(lat, lng))
    } else {
      return(c(NA,NA))
    }
  })
  if(length(address)>1) colnames(coord)=c("lat","lng")
  else names(coord)=c("lat","lng")
  return(data.frame(address,coord))
}

EDIT: Small correction in code so that lat and lng are returned as numerical values.

请帮我爱他 2024-09-17 05:26:20

我需要从 geocode 获取所有返回的地址,而不仅仅是第一个地址,因此我编写了一个小函数来执行此操作。它可用于地理编码反向地理编码

geocode <- function(address,reverse=FALSE)  {
  require("RJSONIO")
  baseURL <- "http://maps.google.com/maps/api/geocode/json?sensor=false&"

  # This is not necessary, 
  # because the parameter "address" accepts both formatted address and latlng

  conURL <- ifelse(reverse,paste0(baseURL,'latlng=',URLencode(address)),
                                  paste0(baseURL,'address=',URLencode(address)))  
  con <- url(conURL)  
  data.json <- fromJSON(paste(readLines(con), collapse=""))
  close(con) 
  status <- data.json["status"]
 if(toupper(status) == "OK"){
  t(sapply(data.json$results,function(x) {
      list(address=x$formatted_address,lat=x$geometry$location[1],
                                                 lng=x$geometry$location[2])}))
 } else { 
   warning(status)
   NULL 
 }
}

地理编码示例:

地理编码(“Dupont Cir NW,华盛顿特区 20036,美国”)

     address                                                               lat      lng      
[1,] "Dupont Circle Northwest, Washington, DC 20036, USA"                  38.90914 -77.04366
[2,] "Dupont Circle, 1 Dupont Circle Northwest, Washington, DC 20036, USA" 38.90921 -77.04438
[3,] "Washington, DC 20036, USA"                                           38.90808 -77.04061
[4,] "Dupont Circle, Washington, DC 20036, USA"                            38.90958 -77.04344

反向地理编码示例:

请注意,地址可以是格式化地址或 latlng(反向)未使用参数,但它包含供将来与其他地理编码服务一起使用

地理编码(“38.910262,-77.043565”)

     address                                                    lat      lng      
[1,] "40-58 Dupont Circle Northwest, Washington, DC 20036, USA" 38.91027 -77.04357
[2,] "Washington, DC 20036, USA"                                38.90808 -77.04061
[3,] "Dupont Circle, Washington, DC, USA"                       38.90969 -77.04334
[4,] "Northwest Washington, Washington, DC, USA"                38.94068 -77.06796
[5,] "District of Columbia, USA"                                38.90598 -77.03342
[6,] "Washington, DC, USA"                                      38.90723 -77.03646
[7,] "United States"                                            37.09024 -95.71289

I needed to get all the returned addresses from geocode not just the first one, so I wrote a small function to do so. It can be used to geocode and to reverse geocode

geocode <- function(address,reverse=FALSE)  {
  require("RJSONIO")
  baseURL <- "http://maps.google.com/maps/api/geocode/json?sensor=false&"

  # This is not necessary, 
  # because the parameter "address" accepts both formatted address and latlng

  conURL <- ifelse(reverse,paste0(baseURL,'latlng=',URLencode(address)),
                                  paste0(baseURL,'address=',URLencode(address)))  
  con <- url(conURL)  
  data.json <- fromJSON(paste(readLines(con), collapse=""))
  close(con) 
  status <- data.json["status"]
 if(toupper(status) == "OK"){
  t(sapply(data.json$results,function(x) {
      list(address=x$formatted_address,lat=x$geometry$location[1],
                                                 lng=x$geometry$location[2])}))
 } else { 
   warning(status)
   NULL 
 }
}

Geocode example:

geocode("Dupont Cir NW, Washington, DC 20036, USA")

     address                                                               lat      lng      
[1,] "Dupont Circle Northwest, Washington, DC 20036, USA"                  38.90914 -77.04366
[2,] "Dupont Circle, 1 Dupont Circle Northwest, Washington, DC 20036, USA" 38.90921 -77.04438
[3,] "Washington, DC 20036, USA"                                           38.90808 -77.04061
[4,] "Dupont Circle, Washington, DC 20036, USA"                            38.90958 -77.04344

Reverse Geocode example:

note that the address can be either formatted address or latlng, the reverse parameter is not used but it is including for future use with other geocoding services

geocode("38.910262, -77.043565")

     address                                                    lat      lng      
[1,] "40-58 Dupont Circle Northwest, Washington, DC 20036, USA" 38.91027 -77.04357
[2,] "Washington, DC 20036, USA"                                38.90808 -77.04061
[3,] "Dupont Circle, Washington, DC, USA"                       38.90969 -77.04334
[4,] "Northwest Washington, Washington, DC, USA"                38.94068 -77.06796
[5,] "District of Columbia, USA"                                38.90598 -77.03342
[6,] "Washington, DC, USA"                                      38.90723 -77.03646
[7,] "United States"                                            37.09024 -95.71289
十雾 2024-09-17 05:26:20

这也可以通过我的包 googleway 和有效的 Google 来完成地图 API 密钥

library(googleway)

key <- "your_api_key"

df <- google_geocode("Philadelphia, PA",
                      key = key)

df$results$geometry$location
#        lat       lng
# 1 39.95258 -75.16522

并进行反向地理编码

df <- google_reverse_geocode(location = c(39.95258, -75.16522),
                             key = key)

df$results$formatted_address
# [1] "1414 PA-611, Philadelphia, PA 19102, USA"           "15th St Station - MFL, Philadelphia, PA 19102, USA"
# [3] "Center City West, Philadelphia, PA, USA"            "Center City, Philadelphia, PA, USA"                
# [5] "Philadelphia, PA, USA"                              "Philadelphia, PA 19107, USA"                       
# [7] "Philadelphia County, PA, USA"                       "Philadelphia-Camden-Wilmington, PA-NJ-DE-MD, USA"  
# [9] "Philadelphia Metropolitan Area, USA"                "Pennsylvania, USA"                                 
# [11] "United States" 

This can also be done with my package googleway and a valid Google Maps API key

library(googleway)

key <- "your_api_key"

df <- google_geocode("Philadelphia, PA",
                      key = key)

df$results$geometry$location
#        lat       lng
# 1 39.95258 -75.16522

And to reverse-geocode

df <- google_reverse_geocode(location = c(39.95258, -75.16522),
                             key = key)

df$results$formatted_address
# [1] "1414 PA-611, Philadelphia, PA 19102, USA"           "15th St Station - MFL, Philadelphia, PA 19102, USA"
# [3] "Center City West, Philadelphia, PA, USA"            "Center City, Philadelphia, PA, USA"                
# [5] "Philadelphia, PA, USA"                              "Philadelphia, PA 19107, USA"                       
# [7] "Philadelphia County, PA, USA"                       "Philadelphia-Camden-Wilmington, PA-NJ-DE-MD, USA"  
# [9] "Philadelphia Metropolitan Area, USA"                "Pennsylvania, USA"                                 
# [11] "United States" 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文