2012-02-26 15 views
25

Nota: Esta pregunta es específica para el mapeo, pero me gustaría poder usarla cuando grafico en un sistema de coordenadas cartesianas estándar.equivalente de localizador en ggplot2 (para mapas)

Me encantan los gráficos base pero también me gusta ggplot2 para muchas cosas. Una de las funciones básicas más utilizadas para ajustar un gráfico es el localizador (n) pero produce un error en 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) 

Ahora grid.locator() como me señaló por Dason en talkstats.com (HERE) puede devolver algo. Simplemente no sé cómo usar ese algo para obtener una coordenada del mapa.

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

$y 
[1] 133native 

Las unidades no parecían ayudar porque no son las coordenadas del mapa. Tal vez necesito algún tipo de conversión.

Gracias de antemano.

EDIT: (basado en la respuesta de Dwin)

Dwin el mundo tiene la idea correcta, pero el factor de conversión es un poco apagado. La ayuda con eso sería apreciada. En el siguiente ejemplo, tengo un mapa con un punto rojo en las coordenadas (x = -73 & y = 40.855). Lancé la respuesta de Dwin a una función para devolver las coordenadas. Esperaría que los resultados sean las coordenadas que coloco pero no lo son.

Ideas?

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 

EDIT 2: (Yendo fuera de la respuesta de Baptise)

estamos allí

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 

ACTUALIZACIÓN:La función gglocator del ggmap package contiene ahora esta funcionalidad

+2

similares, debido a los cambios en ggplot2, ggLocator de ggmap ya no funciona: https://github.com/dkahle/ggmap/issues/87 –

Respuesta

7

que obtener el resultado correcto si agregar scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0)) a la trama, y ​​seekViewport("panel-3-4") antes grid.locator()

+0

Sigo la parte scale_x y y pero seekViewport no. I het el siguiente error: '> seekViewport (" panel-3-4 ") Error en grid.Call.graphics (L_downviewport, name $ name, strict): Viewport 'panel-3-4' no se ha encontrado' –

+1

tal vez su panel de trazado tenga un nombre diferente. Trate de encontrarlo con 'grid.ls()' – baptiste

+0

@batise Lo encontré con grid.ls y he tratado de automatizar el proceso (quiero hacer una función de esto) con 'x <- grid.ls() [ [1]] [grep ("panel-", grid.ls() [[1]])] #locate el panel' que luego alimentaré para seekViewport como 'seekViewport (x)'. Esto parece dar la latitud correcta pero no la longitud (aunque solo lo he probado en este punto). Se está acercando. –

9

necesidad de utilizar un sistema de unidades que tiene sentido y guardar la información en el objeto ggplot para que pueda convertir de unidades "NPC" mapear unidades:

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 
+0

Gracias por su respuesta. Tu respuesta tiene mucho sentido y yo lo intenté. Resulta en un factor de conversión que nos lleva por el camino correcto, pero no allí. ¿Alguna idea de cómo solucionarlo? Por favor revisa mi edición en el OP. –

+1

Imagino que para que las unidades "npc" tengan sentido, deben obtenerse desde la ventana del panel de trazado. Pruebe '? SeekViewport()' primero para navegar a la ventana gráfica, luego las unidades deberían estar relacionadas con los datos. – baptiste

+0

He intentado editar desde mi iPhone pero las barras de desplazamiento no se han procesado, así que tendré que dirigirme más tarde hoy. –

5

Aquí está el resultado final usando todo lo que DWin y Baptise me dieron envuelto en una función. También investigué en la lista de ayuda ggplot e informaré e información adicional aquí.

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) 
5

escribí a la lista ggplot ayuda y recibieron una respuesta muy útil de David Kahle que pasó a interesarse por el mismo problema.Su función es grande en los que:

1) usted no tiene que agregar escala y y x escala de la trama

2) se puede encontrar varios puntos a la vez y devolverlos como datos marco

3) funciona en cualquier tipo de ggplot, no sólo los mapas de

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() 

UPD ATE:La función gglocator del ggmap package ahora contiene esta funcionalidad.

+2

es un paso adelante, pero aún no del todo satisfactorio: 1) probablemente arroje resultados incorrectos si los ejes no son lineales, 2) probablemente falle de alguna manera cuando hay múltiples paneles/tramas en la página. – baptiste

1

Estas publicaciones fueron muy útiles, pero han pasado algunos años, por lo que algunas cosas se han roto. Aquí hay un nuevo código que funciona para mí. El código para encontrar la ventana gráfica correcta no funcionó, así que en su lugar usé current.vpTree() para buscar manualmente la ventana gráfica correcta, y luego copié eso en seekViewport(). Tenga en cuenta que la ventana gráfica era 'panel.6-4-6-4' y no el antiguo panel-*. Finalmente, no obtenía las respuestas correctas cuando renderizaba en rstudio, en cambio tuve que usar x11().

Aquí hay un ejemplo completo. Espero que esto sea útil.

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