Search code examples
rggmap

"non-numeric argument to binary operator" in ggmap


This question has been updated several times.

This is a further question from how to create data frames (not just one) at once in r. I really can't understand the error message. I have two data frames:

> route1
                      X1                         X2                         X3
1 Balboa Park, san diego, ca    Coronado, san diego, ca  USS Midway, san diego, ca
2 Balboa Park, san diego, ca  USS Midway, san diego, ca    Coronado, san diego, ca
3    Coronado, san diego, ca Balboa Park, san diego, ca  USS Midway, san diego, ca
4    Coronado, san diego, ca  USS Midway, san diego, ca Balboa Park, san diego, ca
5  USS Midway, san diego, ca Balboa Park, san diego, ca    Coronado, san diego, ca
6  USS Midway, san diego, ca    Coronado, san diego, ca Balboa Park, san diego, ca

and

> place
# A tibble: 8 x 5
  name                                                hour type  short                abbr  
* <chr>                                              <dbl> <chr> <chr>                <chr> 
1 Balboa Park, san diego, ca                             4 place Balboa Park          bal   
2 USS Midway, san diego, ca                              2 place USS Midway           midway
3 Coronado, san diego, ca                                4 place Coronado             coro  
4 Cabrillo National Monument, san diego, ca              2 place Cabrillo             cab   
5 La Jolla Cove, san diego, ca                           2 place La Jolla             ljc   
6 4002 Wallace St, San Diego, CA 92110                   4 place Old Town             ot    
7 Hotel Republic San Diego, Autograph Collection        NA hotel Autograph Collection NA    
8 THE US GRANT, a Luxury Collection Hotel, San Diego    NA hotel Luxury Collection    NA    

My idea is using ggmap package to get driving time from Hotel Republic San Diego, Autograph Collection (place$name[7]) to the first place in route1's first row, then get driving time from the first place in route1's first row to the second place in route1's first row, and so on, until from the last place in route1's first row to THE US GRANT, a Luxury Collection Hotel, San Diego(place$name[8]). Sum up the time, store in route1$time column. Then do the same thing for the following rows. So my code is

library(ggmap)
register_google(key = "my_google_key_here")
route1$time <- 0
for (i in 1:length(route1)) {
  for (j in 1:length(route1[i,])) {
    if(j == 1){
      route1$time[i] <- route1$time[i] + mapdist(from = place$name[7], to = as.character(route1[i,][1]))$seconds
    }
    if(j == length(route1[i,])){
        route1$time[i] <- route1$time[i] + mapdist(from = as.character(route1[i,][j]), to = place$name[8])$seconds
        route1$time[i] <- route1$time[i] + mapdist(from = as.character(route1[i,][j - 1]), to = as.character(route1[i,][j]))$seconds
    }
    for (j in 2:length(route1[i,]-1)) {
      route1$time[i] <- route1$time[i] + mapdist(from = as.character(route1[i,][j - 1]), to = as.character(route1[i,][j]))$seconds
    }
  }
}

Executing this code gives me

Error in FUN(left, right) : non-numeric argument to binary operator

error message, I think it is saying that I add a character to a number, but I can't find it.


Solution

  • # this is a nice library for R
    library(tidyverse)
    
    # name your variables
    # (you can use these as arguments to a function or something)
    start = place$name[7]
    end = place$name[8]
    
    # wrap your computation into a function which takes
    # a row of a data frame as input    
    compute_route_time = function(row) {
      # get a vector of stops that you can loop through
      stops = unlist(row)
    
      # distance from start to first stop
      time = mapdist(from = start, to = stops[1])$seconds
      # iterate through the rest of the route
      n_stops = length(stops)
      for (i in 1:(n_stops-1)) {
        time = time + mapdist(from = stops[i], to = stops[i+1])$seconds
      }
      # finish rout
      time = time + mapdist(from = stops[n_stops], to = end)$seconds
    
      # collect row as a data frame to preserve old columns
      row = as.data.frame(row)
      # add time column
      row$time = time
      return(row)
    }
    
    route1 %>%
      dplyr::rowwise() %>%
      dplyr::do(compute_route_time(.))