Эквивалент локатора в ggplot2 (для карт) - PullRequest
26 голосов
/ 26 февраля 2012

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

Я люблю базовую графику, но такжекак ggplot2 для многих вещей.Одна из моих наиболее часто используемых базовых функций для тонкой настройки графа - это locator (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

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

Заранее спасибо.

РЕДАКТИРОВАТЬ: (основываясь на ответе DWin)

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

Идеи?

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 

ОБНОВЛЕНИЕ: gglocatorфункция пакета ggmap теперь содержит эту функцию.

Ответы [ 5 ]

9 голосов
/ 26 февраля 2012

Необходимо использовать систему единиц, которая имеет смысл, и сохранять информацию в объекте 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
7 голосов
/ 27 февраля 2012

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

5 голосов
/ 27 февраля 2012

Я написал в справочный список 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()

ОБНОВЛЕНИЕ: Функция gglocator пакета ggmap теперь содержит эту функцию.

5 голосов
/ 27 февраля 2012

Вот окончательные результаты с использованием всего, что дали мне 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)
3 голосов
/ 22 сентября 2017

Эти посты были очень полезны, но прошло несколько лет, поэтому некоторые вещи были нарушены.Вот новый код, который работает для меня.Код для поиска правильного окна просмотра не работал, поэтому вместо этого я использовал 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
...