Подтвердить что ты не робот

Эквивалент локатора в ggplot2 (для карт)

Примечание. Этот вопрос специфичен для сопоставления, но я хотел бы иметь возможность использовать его при построении в стандартной декартовой системе координат.

Мне нравится базовая графика, но также как и ggplot2 для многих вещей. Одной из наиболее используемых базовых функций для точной настройки графика является локатор (n), но это вызывает ошибку в ggplot2.

library(ggplot2) 
county_df <- map_data('county')  #mappings of counties by state
ny <- subset(county_df, region=="new york")   #subset just for NYS
ny$county <- ny$subregion

ggplot(ny, aes(long, lat, group=group)) +  geom_polygon(colour='black', fill=NA)
locator(1)

Теперь grid.locator(), как указал мне Dason на talkstats.com(ЗДЕСЬ) может что-то вернуть. Я просто не знаю, как использовать это, чтобы получить координату карты.

> grid.locator()
$x
[1] 286native

$y
[1] 133native

Единицы не помогли, поскольку они не являются координатами карты. Может быть, мне нужно какое-то преобразование.

Спасибо заранее.

EDIT: (на основе ответа DWin)

У Двина была правильная идея, но коэффициент перевода немного ушел. Помощь с этим будет оценена. В приведенном ниже примере у меня есть карта с красной точкой на ней в координатах (x = -73 и y = 40.855). Я отбросил ответ Dwin в функцию, чтобы вернуть координаты. Я ожидаю, что результаты будут координатами, которые я вставляю, но они не являются.

Идеи?

require(maps); library(ggplot2); require(grid)

county_df <- map_data('county')  #mappings of counties by state
ny <- subset(county_df, region=="new york")   #subset just for NYS
ny$county <- ny$subregion


NY <- ggplot(ny, aes(long, lat)) +  
          geom_polygon(aes(group=group), colour='black', fill=NA) +
          coord_map() + geom_point(aes(-73, 40.855, colour="red"))
NY  

gglocator <- function(object){
    require(maps); require(grid)
    z <- grid.locator("npc")
    y <- sapply(z, function(x) as.numeric(substring(x, 1, nchar(x))))
    locatedX <- min(object$data$long) + y[1]*diff(range(object$data$long))
    locatedy <- min(object$data$lat)  + y[2]*diff(range(object$data$lat))
    return(c(locatedX, locatedy))
}

#click on the red dot
gglocator(NY)  #I expect the results to be x = -73 & y = 40.855

РЕДАКТИРОВАТЬ 2: (Отключение ответа на крещение)

Мы там

NY <- ggplot(ny, aes(long, lat)) +  
          geom_polygon(aes(group=group), colour='black', fill=NA) +
          coord_map() + geom_point(aes(-73, 40.855, colour="red")) +
          scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))


NY 
x <- grid.ls()[[1]][grep("panel-", grid.ls()[[1]])] #locate the panel
seekViewport(x)
y <-  grid.locator("npc")
y <- as.numeric(substring(y, 1, nchar(y)-3))

locatedX <- min(NY$data$long) + y[1]*diff(range(NY$data$long))
locatedy <- min(NY$data$lat) + y[2]*diff(range(NY$data$lat))
locatedX; locatedy 

UPDATE: Функция gglocator ggmap package теперь содержит эту функциональность.

4b9b3361

Ответ 1

Я получаю правильный результат, если я добавляю scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0)) к сюжету, а seekViewport("panel-3-4") до grid.locator()

Ответ 2

Необходимо использовать единую систему, которая имеет смысл и сохраняет информацию в объекте ggplot, чтобы вы могли конвертировать из блоков "npc" в единицы карты:

require(maps)
require(grid)
NY <- ggplot(ny, aes(long, lat, group=group)) +  geom_polygon(colour='black', fill=NA)
 grid.locator("npc")
# clicked in middle of NY State:

#$x
#[1] 0.493649231346082npc
#
#$y
#[1] 0.556430446194226npc
 range(NY$data$long)
#[1] -79.76718 -71.87756
 range(NY$data$lat)
#[1] 40.48520 45.01157
 locatedX <- min(NY$data$long) + 0.493649231346082*diff(range(NY$data$long))
 locatedX
#[1] -75.87247
locatedY <- min(NY$data$lat) +  0.556430446194226*diff(range(NY$data$lat))
locatedY
#[1] 43.00381

Ответ 3

Здесь окончательные результаты, используя все, что DWin и Baptise дали мне завернутый в функцию. Я также запросил список справки ggplot и сообщит вам дополнительную информацию.

require(maps); require(ggplot2); require(grid)

ny <- map_data('county', 'new york')

NY1 <- ggplot(ny, aes(long, lat)) +  
          geom_polygon(aes(group=group), colour='black', fill=NA) +
          coord_map() + geom_point(aes(c(-78, -73), c(41, 40.855), 
          colour=c("blue", "red"))) + opts(legend.position = "none") 

NY <- NY1 + scale_x_continuous(expand=c(0,0)) + 
          scale_y_continuous(expand=c(0,0))
          #the scale x and y have to be added to the plot

NY 

ggmap.loc <- function(object){
    x <- grid.ls()[[1]][grep("panel-", grid.ls()[[1]])] #locate the panel
    seekViewport(x)
    y <-  as.numeric(grid.locator("npc"))
    locatedX <- min(object$data$long) + y[1]*diff(range(object$data$long))
    locatedy <- min(object$data$lat) + y[2]*diff(range(object$data$lat))
    return(c(locatedX, locatedy))
}

ggmap.loc(NY)

Ответ 4

Я написал в список справки ggplot и получил очень полезный ответ от Дэвида Келе, которому, похоже, была интересна та же проблема. Его функция отличная:

1) вам не нужно добавлять масштаб y и масштаб x к графику

2) он может сразу найти несколько точек и вернуть их в качестве фрейма данных

3) он работает на любом типе ggplot, а не только на картах

gglocator <- function(n = 1, object = last_plot(), 
    message = FALSE, xexpand = c(.05,0), yexpand = c(.05, 0)){ 

  #compliments of David Kahle
  if(n > 1){
    df <- NULL
    for(k in 1:n){
      df <- rbind(df, gglocator(object = object, message = message, 
        xexpand = xexpand, yexpand = yexpand))
    }
    return(df)
  }

  x <- grid.ls(print = message)[[1]]
  x <- x[ grep("panel-", grid.ls(print=message)[[1]]) ] #locate the panel
  seekViewport(x)
  loc <-  as.numeric(grid.locator("npc"))

  xrng <- with(object, range(data[,deparse(mapping$x)]))
  yrng <- with(object, range(data[,deparse(mapping$y)]))    

  xrng <- expand_range(range = xrng, mul = xexpand[1], add = xexpand[2])
  yrng <- expand_range(range = yrng, mul = yexpand[1], add = yexpand[2])    

  point <- data.frame(xrng[1] + loc[1]*diff(xrng), yrng[1] + loc[2]*diff(yrng))
  names(point) <- with(object, c(deparse(mapping$x), deparse(mapping$y)))
  point
}

#Example 1
require(maps); library(ggplot2); require(grid)
county_df <- map_data('county')  #mappings of counties by state
ny <- subset(county_df, region=="new york")   #subset just for NYS
ny$county <- ny$subregion


NY <- ggplot(ny, aes(long, lat)) +  
          geom_polygon(aes(group=group), colour='black', fill=NA) +
          coord_map() + geom_point(aes(c(-78, -73), c(41, 40.855), 
          colour=c("blue", "red"))) + opts(legend.position = "none") 


NY 
gglocator(2)

#Example 2
df <- data.frame(xvar = 2:10, yvar = 2:10)
ggplot(df, aes(xvar, yvar)) + geom_point() + geom_point(aes(x = 3, y = 6))
gglocator()

UPDATE: Функция gglocator ggmap package теперь содержит эту функциональность.

Ответ 5

Эти сообщения были очень полезными, но прошло несколько лет, поэтому некоторые вещи были нарушены. Вот несколько новых кодов, которые работают для меня. Код для поиска правильного видового экрана не работал, поэтому вместо current.vpTree() я использовал ручной поиск нужного окна просмотра, а затем скопировал его в seekViewport(). Обратите внимание, что для меня был 'panel.6-4-6-4', а не старый стиль panel-*. Наконец, я не получал правильных ответов при рендеринге в rstudio, вместо этого мне пришлось использовать x11().

Вот полный пример. Надеюсь, что это будет полезно.

library(ggplot2)
library(grid)

object<-ggplot(dat=data.frame(x=1:5,y=1:5),aes(x=x,y=y)) + 
  geom_point()  +
  scale_x_continuous(expand=c(0,0)) +
  scale_y_continuous(expand=c(0,0))
x11()
print(object)
formatVPTree(current.vpTree()) #https://www.stat.auckland.ac.nz/~paul/useR2015-grid/formatVPTree.R
seekViewport('panel.6-4-6-4')
y <-  as.numeric(grid.locator("npc"))
locatedX <- min(object$data$x) + y[1]*diff(range(object$data$x))
locatedY <- min(object$data$y) + y[2]*diff(range(object$data$y))
locatedX; locatedY