2012-02-26 10 views
25

Nota: questa domanda è specifica per la mappatura ma mi piacerebbe essere in grado di usarla quando ordino in un sistema di coordinate cartesiane standard.locator equivalente in ggplot2 (per le mappe)

Amo la grafica di base ma mi piace anche ggplot2 per molte cose. Una delle mie funzioni di base più utilizzate per la regolazione fine di un grafico è il locator (n), ma questo produce un errore in 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) 

Ora grid.locator() come mi ha fatto notare da Dason su talkstats.com (HERE) può restituire qualcosa. Non so come usare quel qualcosa per ottenere una coordinata della mappa.

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

$y 
[1] 133native 

Le unità non sembrano aiutare in quanto non sono le coordinate della mappa. Forse ho bisogno di una sorta di conversione.

Grazie in anticipo.

EDIT: (in base alla risposta del DWin)

Dwin del avuto l'idea giusta, ma il fattore di conversione è un po 'fuori. Aiutare con quello sarebbe apprezzato. Nell'esempio seguente ho una mappa con un punto rosso su di essa alle coordinate (x = -73 & y = 40.855). Ho lanciato la risposta di Dwin in una funzione per restituire le coordinate. Mi aspetto che i risultati siano le coordinate che ho inserito, ma non lo sono.

Idee?

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: (Andando fuori della risposta di Baptise)

siamo lì

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:La funzione gglocator del ggmap package ora contiene questa funzionalità

+2

come causa di cambiamenti nella ggplot2, ggLocator da ggmap non funziona più: https://github.com/dkahle/ggmap/issues/87 –

risposta

7

ottengo il risultato corretto se io aggiungi scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0)) alla trama e seekViewport("panel-3-4") prima del grid.locator()

+0

Seguo le parti scale_x e y ma seekViewport non lo faccio. Ho il seguente errore: '> seekViewport (" panel-3-4 ") Errore in grid.Call.graphics (L_downviewport, nome $ name, strict): Viewport 'panel-3-4' non trovato ' –

+1

forse il tuo pannello di trama ha un nome diverso. Prova a trovarlo con 'grid.ls()' – baptiste

+0

@batise L'ho trovato con grid.ls e ho provato ad automatizzare il processo (voglio fare una funzione fuori da questo) con 'x <- grid.ls() [ [1]] [grep ("panel-", grid.ls() [[1]])] #locate il pannello' che poi mando a seekViewport come 'seekViewport (x)'. Questo sembra dare la latitudine corretta ma non la longitudine (sebbene l'ho solo testata su questo punto). Si sta avvicinando. –

9

necessità di utilizzare un sistema di unità che ha un senso e salvare le informazioni nell'oggetto ggplot in modo da poter convertire da "NPC" unità di mappare le unità:

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

Grazie per la vostra risposta. La tua risposta ha molto senso e l'ho provata. Il risultato è un fattore di conversione che ci sta portando sulla strada giusta ma non lì. Qualche idea su come risolverlo? Si prega di controllare la mia modifica nell'OP. –

+1

Immagino che per le unità "npc" abbia senso aver bisogno di essere ottenuto dalla finestra del riquadro di trama. Prova '? SeekViewport()' prima di navigare verso la vista, quindi le unità dovrebbero essere correlate ai dati. – baptiste

+0

Ho provato a modificare dal mio iPhone ma le barre di scorrimento non sono state renderizzate, quindi dovrò parlarne più tardi oggi. –

5

Ecco i risultati finali utilizzando tutto ciò che DWin e Baptise mi hanno assegnato in una funzione. Ho anche chiesto la lista di aiuto di ggplot e riferirò e ulteriori informazioni qui.

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

ho scritto alla lista ggplot aiuto e ha ricevuto una risposta molto utile da David Kahle che è accaduto a essere interessato lo stesso problema.La sua funzione è grande in quanto:

1) non c'è bisogno di aggiungere y scala e la scala x per la trama

2) che riesce a trovare più punti in una sola volta e restituirli come dati cornice

3) funziona su qualsiasi tipo di ggplot, non solo le mappe

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 funzione gglocator di ggmap package contiene ora questa funzionalità.

+2

è un passo avanti, ma ancora non del tutto soddisfacente: 1) probabilmente restituisce risultati errati se gli assi non sono lineari, 2) probabilmente fallisce in qualche modo quando ci sono più pannelli/grafici sulla pagina. – baptiste

1

Questi post sono stati molto utili, ma sono passati alcuni anni, quindi alcune cose si sono rotte. Ecco un nuovo codice che funziona per me. Il codice per trovare la vista corretta non funzionava, quindi ho usato current.vpTree() per cercare manualmente la viewport corretta, quindi lo ho copiato in seekViewport(). Nota che il viewport per me era 'panel.6-4-6-4' e non il vecchio stile panel-*. Infine, non stavo ottenendo le risposte giuste durante il rendering in rstudio, invece ho dovuto usare x11().

Ecco un esempio completo. Spero che questo sia utile.

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 
Problemi correlati