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.
The easiest way to create spatial plots with ggplot is to use the geom_sf() function. By default there is no aesthetic mapping, but we can use arguments like fill to easily create choropleth maps.
ggplot2 is a system for declaratively creating graphics, based on The Grammar of Graphics. You provide the data, tell ggplot2 how to map variables to aesthetics, what graphical primitives to use, and it takes care of the details.
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
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, and seekViewport("panel-3-4")
before grid.locator()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With