【问题标题】:Geocoding with R and Googlemaps API使用 R 和 Googlemaps API 进行地理编码
【发布时间】:2014-05-14 06:55:12
【问题描述】:

我经常使用 R 进行统计分析,但正在慢慢尝试使用 R 转向 GIS 和空间可视化。

我正在尝试复制

上提供的地理编码代码

https://github.com/smholloway/data-mashups-in-r/blob/master/mapping-foreclosures.r#L14

然而,在运行地理编码功能时,我收到以下错误消息

geocoding: http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=5833%20Ashland%20Ave.+Philadelphia+PA 
parsing or http error: $ operator is invalid for atomic vectors 

geocoding: http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=219-221%20E.%20Tioga%20St.+Philadelphia+PA 
parsing or http error: arguments imply differing number of rows: 1, 0 

关于我应该怎么做才能使这段代码工作的任何建议?

这是我正在运行的代码的片段

library("XML")
library("rjson")
library("RCurl")
library("PBSmapping")

if (!file.exists("properties.html")) {
  download.file(url="http://web.archive.org/web/20080610132249/www.phillysheriff.com/properties.html", destfile="properties.html")
}


########################
# getAddressesFromHTML
# input:html filename
# returns:dataframe of geocoded addresses that can be plotted by PBSmapping
########################
getAddressesFromHTML<-function(myHTMLDoc){
  myStreets<-vector(mode="character",0)
  stNum<-"^[0-9]{2,5}(\\-[0-9]+)?"
  stName<-"([NSEW]\\. )?([0-9A-Z ]+)"
  stSuf<-"(St|Ave|Place|Blvd|Drive|Lane|Ln|Rd)(\\.?)$"
  badStrings<-
    "(\\r| a\\/?[kd]\\/?a.+$| - Premise.+$| assessed as.+$|, Unit.+
     |<font size=\"[0-9]\">|Apt\\..+| #.+$|[,\"]|\\s+$)"
  myStPat<-paste(stNum,stName,stSuf,sep=" ")
  for(line in readLines(myHTMLDoc)){
    line<-gsub(badStrings,'',line,perl=TRUE)
    matches<-grep(myStPat,line,perl=TRUE,
                  value=FALSE,ignore.case=TRUE)
    if(length(matches)>0){
       myStreets<-append(myStreets,line)
    }
  }
  myStreets 
}

####################
# geocodeAddresses
# input:vector of streets
# output:data frame containing lat/longs in PBSmapping-acceptable format
####################
geocodeAddresses<-function(myStreets){
  myGeoTable<-data.frame(address=character(),lat=numeric(),long=numeric(),EID=numeric())
  for(myStreet in myStreets){
     requestUrl<-paste(
          "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=", 
          URLencode(myStreet),
          "+Philadelphia+PA",
          sep="")
    cat("geocoding:", requestUrl, "\n")
    tryCatch({
        json_data <- fromJSON(paste(readLines(requestUrl), collapse=""))
        lat <- unlist(lapply(json_data$results, function(x) {x$geometry[1]$location$lat}))
        lng <- unlist(lapply(json_data$results, function(x) {x$geometry[1]$location$lng}))

        myGeoTable<-rbind(myGeoTable,data.frame(address = myStreet, Y = lat, X = lng, EID=NA))
    }, error=function(err) {
        cat("parsing or http error:", conditionMessage(err), "\n")
    })
    Sys.sleep(0.1)
  }

  #let's use the built-in numbering as the event id that PBSmapping wants
  myGeoTable$EID<-as.numeric(rownames(myGeoTable))
  myGeoTable
}

streets<-getAddressesFromHTML("properties.html")



geoTable<-geocodeAddresses(streets)

【问题讨论】:

    标签: r google-maps-api-3 geocode rjson


    【解决方案1】:

    您可以使用 ggmaps 函数 geocode("location") 但有 2500 个查询限制。

    这是一个可让您使用 Bing Maps API 的函数(一生中限制为 500,000 个)。您必须注册微软市场,但它是免费的。

    #Google Maps API limits querys to 2500 per day and fails to geocode smaller towns. So I wrote a function to geocode using Bing's API. It's also much faster.
    geocode <- function( x, verbose=FALSE, service="google", returntype="coordinates", ... ) {
      UseMethod("geocode",x)
    }
    geocode.default <- function(x,verbose=FALSE, service="google", returntype="coordinates", ...) {
      if( is.na( x ) | gsub(" *", "", x) == ""  ) return(c(NA,NA))
      service <- tolower(service)
      BingMapsKey <- getOption("BingMapsKey")
      if(service=="bing" && is.null(BingMapsKey) ) stop("To use Bing, you must save your Bing Maps API key (obtain at http://msdn.microsoft.com/en-us/library/ff428642.aspx) using options(BingMapsKey='mykey').\n")
      construct.geocode.url <- list()
      construct.geocode.url[["google"]] <- 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))  
      }
      construct.geocode.url[["bing"]] <- function(address, maxResults=1) {
        root <- "http://dev.virtualearth.net/REST/v1/Locations"
        u <- paste0(root, "?query=", address, "&maxResults=",maxResults,"&key=",BingMapsKey)
        return(URLencode(u))
      }
      if(verbose) message(x,appendLF=FALSE)
      u <- construct.geocode.url[[service]](x)
      doc <- RCurl::getURL(u)
      j <- RJSONIO::fromJSON(doc,simplify = FALSE)
      parse.json <- list()
      parse.json[["google"]] <- function(j) {
        if(j$status=="OK") {
          res <- list()
          if( "coordinates" %in% returntype ) {
            lat <- j$results[[1]]$geometry$location$lat
            lng <- j$results[[1]]$geometry$location$lng
            res$coordinates <- c(lat, lng)
          }
          if( "zip" %in% returntype )  {
            zp <- j$results[[1]]$address_components[[8]]$short_name
            if( j$results[[1]]$address_components[[8]]$types[[1]] != "postal_code" )  warning(paste("Not sure these zips are actually zips.  Type:", j$results[[1]]$address_components[[8]]$types[[1]]) )
            res$zip <- zp
          }
          return( res )
        } else {
          if(j$status=="OVER_QUERY_LIMIT") warning("Google's geocoding quota appears to have been reached for the day.")
          return(c(NA,NA))
        }
      }
      parse.json[["bing"]] <- function(j) {
        if(j$authenticationResultCode != "ValidCredentials") {
          warning("Your BingMapsKey was not accepted.")
          return(c(NA,NA))
        }
        if(j$statusDescription!="OK") {
          warning("Something went wrong. Bing Maps API return status code ",j$statusCode," - ", j$statusDescription)
          return(c(NA,NA))
        }
        if(j$resourceSets[[1]]$estimatedTotal==0) {
          warning("Didn't find any points")
          return(c(NA,NA))
        }
        if(verbose) message(" - Confidence: ", j$resourceSets[[1]]$resources[[1]]$confidence ,appendLF=FALSE)
        res <- list()
        if( "coordinates" %in% returntype ) {
          crds <- unlist(j$resourceSets[[1]]$resources[[1]]$point$coordinates)
          res$coordinates <- crds
        }
        if( "zip" %in% returntype )  {
          res$zip <- sub( "^.*(\\d{5}-?\\d?\\d?\\d?\\d?).*$", "\\1", j$resourceSets[[1]]$resources[[1]]$address$formattedAddress )
        }
        return( res )
      }
      res <- parse.json[[service]](j)
      if(length(returntype)==1) res <- res[[1]]
      if(verbose) message("\n",appendLF=FALSE)
      return( res )
    }
    
    #Vectorize function
    geocodeVect <- Vectorize(geocode, vectorize.args="x")
    
    #Batch geocode with Bing
    options(BingMapsKey="YourBingAPIkey")
    
    data<-geocodeVect(data, service="bing", 
                           returntype="coordinates")
    data <-as.data.frame(t(as.data.frame(data)))
    data $location<-rownames(data)
    rownames(data)<-NULL
    

    【讨论】:

    • 您对@Cyrus Mohammadian 函数有疑问吗?
    • @Wilcar 您面临什么问题?你有错误吗?
    • 我将用你的函数发布一个带有小数据示例的问题。我工作,但问题不是很好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2015-10-30
    • 2015-11-02
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多