Геокодирование в R с Google Maps - PullRequest
25 голосов
/ 15 июля 2010

Я пытался запустить код для геокодирования местоположений в R с помощью Google Maps и пакета XML из этого сообщения в блоге: 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"

Если я просто вставлю в браузер URL-адрес API с добавлением Philadelphia, PA в конец, как строка, переданная в xmlParseTree, я получу результат, который выглядит как допустимый xml при его загрузке.

Это проблема с кодом, или мне не удалось настроить то или другое?

Ответы [ 6 ]

23 голосов
/ 16 июля 2010

Думали ли вы использовать вместо этого вызов json? Глядя на ваш код, вы можете добиться того же самого, выполняя это (вам нужно установить пакеты RCurl и RJSONIO с omegahat.com).

Скопируйте и вставьте это в 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

Надеюсь, это поможет немного приятель,

Тони Бреял

5 голосов
/ 13 января 2011

Этот код работает с использованием только библиотеки 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]]))
3 голосов
/ 15 июля 2010

Это еще один вариант для геокодирования - его легче разобрать:

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

2 голосов
/ 14 июня 2014

Мне нужно было получить все возвращенные адреса от 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, 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

Пример обратного геокода:

обратите внимание, что адрес может быть либо форматированным адресом, либо значением latlng, параметр reverse не используется, но он используется в будущем для других служб геокодирования

геокод ("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
2 голосов
/ 06 мая 2013

Я изменил решение 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"

Обратите внимание, что API карт Google имеет дневной лимит 2500, поэтому ваш вектор не долженбыть слишком длиннымВот обновленная функция:

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: Небольшое исправление в коде, так что lat и lng возвращаются как числовые значения.

0 голосов
/ 01 июля 2016

Это также можно сделать с моим пакетом googleway и действующим ключом API Карт Google

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" 
...