Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
641 views
in Technique[技术] by (71.8m points)

r - locator equivalent in ggplot2 (for maps)

Note: This question is specific for mapping but I'd like to be able to use it when I plot in a standard Cartesian coordinate system.

I love base graphics but also like ggplot2 for many things. One of my most used base functions for fine tuning a graph is locator(n) but this produces an error 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)

Now grid.locator() as pointed out to me by Dason on talkstats.com (HERE) can return something. I just don't know how to use that something to get a map coordinate.

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

$y
[1] 133native

Units didn't seem to help as they are not map coordinates. Maybe I need some sort of conversion.

Thank you in advance.

EDIT: (based on DWin's response)

Dwin's got the right idea but the conversion factor is a little bit off. Help with that would be appreciated. In the example below I have a map with a red dot on it at the coordinates (x = -73 & y = 40.855). I threw Dwin's response into a function to return the coordinates. I would expect the results to be the coordinates I put in but they're not.

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: (Going off of Baptise's answer)

We're there

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: The gglocator function of the ggmap package now contains this functionality.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Need to use a unit system that makes sense and save the information in the ggplot object so you can convert from "npc" units to map units:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...