Создание base_layer для ggmap, не распознающего data.frame

Я пытаюсь использовать ggmap для отображения местоположения на карте. Поскольку я хочу использовать фасетирование, я должен указать аргумент base_layer для ggmap. Я также пытаюсь обернуть это в функцию.

У меня есть переменные, которые определяют ограничивающую рамку моей карты:

long.range <- c(-71.5, -67.5)
lat.range <- c(42.5, 44.5)

И data.frame, который определяет данные, которые я хочу построить:

test.data <- data.frame("Name" = c("site1","site2","site3"),
                        "LAT" = c(43.25,43.4,44),
                        "LONG" = c(-71.25,-69.5,-68.5))

У меня есть функция, которая берет карту и применяет data.frame в качестве базового слоя:

CreateBaseMap <- function(lat.range = c(NA,NA),
                          long.range = c(NA,NA),
                          data.in = NULL){    
  # download the map tile
  base.map.in <- get_map(location = c(min(long.range),
                                      min(lat.range),
                                      max(long.range),
                                      max(lat.range)),
                         source = "osm")
  # create the map object
  if (is.null(data.in)){
    base.map <- ggmap(base.map.in)
  } else {    
    base.map <- ggmap(base.map.in,
                      base_layer = ggplot(aes_string(x = "LONG",
                                                     y = "LAT"),
                                          data = data.in))
  }
  base.map <- base.map +
    labs(x = "Longitude",
         y = "Latitude") + 
    coord_map()
  print(base.map)
  return(base.map)
}

а затем я вызываю свою функцию, используя

base.map <- CreateBaseMap(lat.range = lat.range, long.range = long.range, data.in = test.data)

и я получаю эту ошибку.

Error in ggplot(aes_string(x = "LONG", y = "LAT"), data = data.in) : 
  object 'data.in' not found

Устранение неполадок на данный момент

Я знаю, если я вызову кишки функции напрямую, вот так:

base.map <- ggmap(get_map(location = c(min(long.range),
                                       min(lat.range),
                                       max(long.range),
                                       max(lat.range)),
                          source = "osm"),
                  base_layer = ggplot(aes_string(x = "LONG",
                                                 y = "LAT"),
                                      data = test.data)) +
  geom_point()
print(base.map)

тогда он работает нормально.

Изображение, которое я хочу

Я также проверил, используя print(data.in), что data.in существует до того, как он дойдет до вызова base_layer, и я вижу, что он там.

Вопрос

Похоже, что вызов base_layer не распознает data.in.

  1. Как я могу убедить base_layer, что он действительно хочет принять data.in?
  2. Это проблема с ggplot или я что-то не так делаю?

person Andy Clifton    schedule 03.07.2013    source источник
comment
дикая догадка: ggplot2 может быть суетливым в отношении окружения при работе внутри функций; IIRC есть несколько примеров на SO.   -  person baptiste    schedule 04.07.2013
comment
Я имел в виду это, но, похоже, это не помогает ggplot. Возможно, это аналогичная проблема с ggmap, но я отказался смотреть этот код.   -  person baptiste    schedule 04.07.2013
comment
Спасибо @baptiste. Я попытался установить environment = environment() в вызове ggplot, но это не помогает. Исходя из фона Matlab, где единственные данные, которые у вас есть, — это то, что вы передаете функции, это сбивает с толку!   -  person Andy Clifton    schedule 04.07.2013
comment
Эм-м-м? Я хорошо помню, что в Matlab было много ловушек с глобальными переменными повсюду. Предполагается, что R как функциональный язык избежит таких опасностей. Это не означает, что весь код R написан правильно.   -  person baptiste    schedule 04.07.2013
comment
если вы пробежитесь по коду ggmap, вы заметите этот бит base <- deparse(eval(args$base_layer)); Я считаю, что проблема именно в этом, поскольку eval() не имеет подходящей среды для поиска ваших данных.   -  person baptiste    schedule 04.07.2013
comment
Тогда есть предложения, как это исправить? Должен ли я убедиться, что я передаю переменную, определенную в основной среде?   -  person Andy Clifton    schedule 04.07.2013
comment
кажется, что единственным способом является ручное редактирование кода ggmap (похоже, он более или менее работает при изменении этих вызовов eval()), но я бы посоветовал вам напрямую связаться с сопровождающим пакета / отправить отчет об ошибке.   -  person baptiste    schedule 04.07.2013


Ответы (1)


Похоже, решение состоит в том, чтобы использовать %+% для элемента ggplot, созданного из вызова ggmap, а не включать base_layer в исходный вызов ggmap. Это позволяет обойти проблему с кодом, обнаруженную @baptiste.

Чтобы реализовать это решение, скопируйте следующий код вместо #create the map object в моем исходном вопросе:

# create the map object
  if (is.null(data.in)){
    base.map <- ggmap(base.map.in)
  } else {    
    base.map <- ggmap(base.map.in ) %+% data.in + aes(x = LONG,
                                                      y = LAT)
  }
person Andy Clifton    schedule 04.07.2013