How to integrate Google Distance Matrix API key in R code?

后端 未结 2 890
悲&欢浪女
悲&欢浪女 2021-01-15 04:07

I have registered in Google to obtain more requests of drive time distances. However Google doesn\'t automatically pick up this \"permission\" to run more than 2500 queries

相关标签:
2条回答
  • 2021-01-15 04:34

    I've written the package googleway to access google maps API where you can specify your token key

    For example
    
    library(googleway)
    key <- "your_api_key"
    
    google_distance(origins = list("houston", "Dallas"),
                    destinations = list("waco, Texas", "San Antonio"),
                    key = key,
                    simplify = FALSE)  ## use simplify = T to simplify to a data.frame
    
    
    [1] "{"                                                                              
    [2] "   \"destination_addresses\" : [ \"Waco, TX, USA\", \"San Antonio, TX, USA\" ],"
    [3] "   \"origin_addresses\" : [ \"Houston, TX, USA\", \"Dallas, TX, USA\" ],"       
    [4] "   \"rows\" : ["                                                                
    [5] "      {"                                                                        
    [6] "         \"elements\" : ["                                                      
    [7] "            {"                                                                  
    [8] "               \"distance\" : {"                                                
    [9] "                  \"text\" : \"299 km\","                                       
    [10] "                  \"value\" : 298585"                                           
    [11] "               },"                                                              
    [12] "               \"duration\" : {"                                                
    [13] "                  \"text\" : \"2 hours 51 mins\","                              
    [14] "                  \"value\" : 10244"                                            
    [15] "               },"                                                              
    [16] "               \"duration_in_traffic\" : {"                                     
    [17] "                  \"text\" : \"2 hours 52 mins\","                              
    [18] "                  \"value\" : 10343"                                            
    [19] "               },"                                                              
    [20] "               \"status\" : \"OK\""                                             
    [21] "            },"
    ... etc
    
    0 讨论(0)
  • 2021-01-15 04:39

    I modified the core code (than I run before the commmand) as follows:

    #' Compute map distances using Google
    #'
    #' Compute map distances using Google Maps. Note that in most cases
    #' by using this function you are agreeing to the Google Maps API
    #' Terms of Service at https://developers.google.com/maps/terms.
    #'
    #' @param from name of origin addresses in a data frame (vector
    #'   accepted)
    #' @param to name of destination addresses in a data frame (vector
    #'   accepted)
    #' @param output amount of output
    #' @param mode driving, bicycling, or walking
    #' @param messaging turn messaging on/off
    #' @param sensor whether or not the geocoding request comes from a
    #'   device with a location sensor
    #' @param language language
    #' @param override_limit override the current query count
    #'   (.GoogleDistQueryCount)
    #' @return a data frame (output="simple") or all of the geocoded
    #'   information (output="all")
    #' @author David Kahle \email{david.kahle@@gmail.com}
    #' @details if parameters from and to are specified as geographic
    #'   coordinates, they are reverse geocoded with revgeocode.  note
    #'   that the google maps api limits to 2500 element queries a day.
    #' @seealso
    #' \url{http://code.google.com/apis/maps/documentation/distancematrix/}
    #'
    #' @export
    #' @examples
    #'
    #' \dontrun{ online queries draw R CMD check times
    #'
    #' mapdist("waco, texas", "houston, texas")
    #'
    #' from <- c("houston, texas", "dallas")
    #' to <- "waco, texas"
    #' mapdist(from, to)
    #' mapdist(from, to, mode = "bicycling")
    #' mapdist(from, to, mode = "walking")
    #'
    #' from <- c("houston", "houston", "dallas")
    #' to <- c("waco, texas", "san antonio", "houston")
    #' mapdist(from, to)
    #'
    #'
    #' # geographic coordinates are accepted as well
    #' (wh <- as.numeric(geocode("the white house, dc")))
    #' (lm <- as.numeric(geocode("lincoln memorial washington dc")))
    #' mapdist(wh, lm, mode = "walking")
    #' distQueryCheck()
    #'
    #' }
    #'
    mapdist <- function(from, to, mode = c("driving","walking","bicycling"),
      output = c("simple","all"), messaging = FALSE, sensor = FALSE,
      language = "en-EN", override_limit = FALSE, key)
    {
    
      message("by using this function you are agreeing to the terms at :")
      message("http://code.google.com/apis/maps/documentation/distancematrix/\n")
    
      # check parameters
      if(is.numeric(from) && length(from) == 2) from <- revgeocode(from)
      stopifnot(is.character(from))
      if(is.numeric(to) && length(to) == 2) to <- revgeocode(to)
      stopifnot(is.character(to))
      from_to_df <- data.frame(from = from, to = to, stringsAsFactors = FALSE)
      origins <- from_to_df$from
      destinations <- from_to_df$to # this ensures # from = # to
      mode <- match.arg(mode)
      output <- match.arg(output)
      stopifnot(is.logical(messaging))
      stopifnot(is.logical(sensor))
    
    
      getdists <- function(df){
    
        # format url
        origin <- df$from[1]
        origin <- gsub(",", "", origin)
        origin <- gsub(" ", "+", origin)
        origin <- paste("origins=", origin, sep = "")
        destinations <- df$to
        destinations <- gsub(",", "", destinations)
        destinations <- gsub(" ", "+", destinations)
        destinations <- paste("destinations=", paste(destinations, collapse = "|"), sep = "")
        mode4url <- paste("mode=", mode, sep = "")
        lang4url <- paste("language=", language, sep = "")
        sensor4url <- paste("sensor=", tolower(as.character(sensor)), sep = "")
        keyUrl <- paste("key=", key, sep = "")
        posturl <- paste(origin, destinations, mode4url, sensor4url, keyUrl, sep = "&")
        url_string <- paste("https://maps.googleapis.com/maps/api/distancematrix/json?",
          posturl, sep = "")
        url_string <- URLencode(url_string)
    
    
        # check if query is too long
        if(nchar(url_string) >= 2048){
          n <- nrow(df)
          half_df <- floor(n/2)
          return(
            rbind(
              getdists(df[half_df,]),
              getdists(df[(half_df+1):n,])
            )
          )
        }
    
        # check/update google query limit
        check_dist_query_limit(url_string, elems = nrow(df),
          override = override_limit, messaging = messaging)
    
    
        # distance lookup
        if(messaging) message("trying url ", url_string)
        connect <- url(url_string)
        tree <- fromJSON(paste(readLines(connect), collapse = ""))
        close(connect)
    
        # message user
        message(paste0("Information from URL : ", url_string))
    
        # label destinations - first check if all were found
        if(length(df$to) != length(tree$destination_addresses)){
          message("matching was not perfect, returning what was found.")
          names( tree$rows[[c(1,1)]] ) <- tree$destination_addresses
          output <<- "all"
          # stringdist::amatch(df$to, tree$destination_addresses, maxDist = 10)
        } else {
          names( tree$rows[[c(1,1)]] ) <- df$to
        }
    
        # return
        tree$rows[[c(1,1)]]
      }
    
      out <- dlply(from_to_df, "from", getdists)
    
      # return all
      if(output == "all") return(out)
    
    
    
      # format output
      out <-
        ldply(out, function(oneFromList){
          ldply(oneFromList, function(oneToList){
            data.frame(
              m = oneToList$distance$value,
              km = oneToList$distance$value/1000,
              miles = 0.0006214 * oneToList$distance$value,
              seconds = oneToList$duration$value,
              minutes = oneToList$duration$value / 60,
              hours = oneToList$duration$value / 3600
            )
          })
        })
    
      names(out) <- c("from", "to", names(out)[3:ncol(out)])
    
      # "simple" return
      suppressMessages(join(from_to_df, out))
    }
    
    
    
    
    check_dist_query_limit <- function(url_string, elems, override, messaging){
      .GoogleDistQueryCount <- NULL; rm(.GoogleDistQueryCount); # R CMD check trick
    
      if(exists(".GoogleDistQueryCount", .GlobalEnv)){
    
        .GoogleDistQueryCount <<-
          subset(.GoogleDistQueryCount, time >= Sys.time() - 24*60*60)
    
        # 2500 per 24 hours
        if(sum(.GoogleDistQueryCount$elements) + elems > 2500){
          message("query max exceeded, see ?mapdist.  current total = ",
            sum(.GoogleDistQueryCount$elements))
          if(!override) stop("google query limit exceeded.", call. = FALSE)
        }
    
        # 100 per 10 seconds
        if(with(.GoogleDistQueryCount,
          sum(elements[time >= Sys.time() - 10]) + elems > 100
        )){
          if(messaging) message("waiting 10 seconds for another 100 queries...", appendLF=F)
          Sys.sleep(10) # can do better
          if(messaging) message(" done")
        }
    
        # append to .GoogleDistQueryCount
        .GoogleDistQueryCount <<- rbind(.GoogleDistQueryCount,
          data.frame(time = Sys.time(),  url = url_string,
            elements = elems, stringsAsFactors = FALSE)
        )
    
    
      } else {
    
        .GoogleDistQueryCount <<-
          data.frame(time = Sys.time(),  url = url_string,
            elements = elems, stringsAsFactors = FALSE)
    
      }
    }
    
    
    
    #' Check Google Maps Distance Matrix API query limit
    #'
    #' Check Google Maps Distance Matrix API query limit
    #'
    #' @return a data frame
    #' @author David Kahle \email{david.kahle@@gmail.com}
    #' @seealso \url{http://code.google.com/apis/maps/documentation/distancematrix/}
    #' @export
    #' @examples
    #' distQueryCheck()
    distQueryCheck <- function(){
      .GoogleDistQueryCount <- NULL; rm(.GoogleDistQueryCount); # R CMD check trick
      if(exists(".GoogleDistQueryCount", .GlobalEnv)){
        remaining <- 2500-sum(
          subset(.GoogleDistQueryCount, time >= Sys.time() - 24*60*60)$elements
          )
        message(remaining, " distance queries remaining.")
      } else {
        remaining <- 2500
        message(remaining, " distance queries remaining.")
      }
      invisible(remaining)
    }
    

    Then I was able to modify the mapdist() command by adding the key name "1234" as follows:

    # create your own 'from' and 'to' variables 
    from <- drivetime$gp_postcode
    to <- drivetime$h_postcode
    
        result <- vector("list")
        for (i in 1:nrow(drivetime)) { # could be 1:nrow(drivetime)
          result[[i]] <- mapdist(from[i], to[i], mode = "driving", override_limit = TRUE, key="1234") 
          Sys.sleep(0.5)
        }
        results <- dput(result)
        res_df <- do.call(rbind, results)
    

    You can follow the number of queries made and the billing here

    0 讨论(0)
提交回复
热议问题