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.
I wrote to the ggplot help list and received a very helpful response from David Kahle who happened to be interested in the same problem. His function is great in that:
1) you don't have to add scale y and scale x to the plot
2) it can find multiple points at once and return them as a data frame
3) it works on any type of ggplot, not just maps
UPDATE: The
gglocator
function of the ggmap package now contains this functionality.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:
I get the correct result if I add
scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
to the plot, andseekViewport("panel-3-4")
beforegrid.locator()
Here's the final results using everything DWin and Baptise gave me wrapped up into a function. I also inquired on the ggplot help list and will report and additional information back here.
These posts were very helpful, but it's been a few years so a few things are broken. Here is some new code that works for me. The code to find the correct viewport didn't work, so instead I used
current.vpTree()
to manually search for the right viewport, then copied that intoseekViewport()
. Note the viewport for me was'panel.6-4-6-4'
and not the old stylepanel-*
. Finally, I wasn't getting the right answers when rendering in rstudio, instead I had to usex11()
.Here is a complete example. Hope this is helpful.