Ответ 1
Я получаю правильный результат, если я добавляю scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
к сюжету, а seekViewport("panel-3-4")
до grid.locator()
Примечание. Этот вопрос специфичен для сопоставления, но я хотел бы иметь возможность использовать его при построении в стандартной декартовой системе координат.
Мне нравится базовая графика, но также как и ggplot2 для многих вещей. Одной из наиболее используемых базовых функций для точной настройки графика является локатор (n), но это вызывает ошибку в 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)
Теперь grid.locator()
, как указал мне Dason на talkstats.com(ЗДЕСЬ) может что-то вернуть. Я просто не знаю, как использовать это, чтобы получить координату карты.
> grid.locator()
$x
[1] 286native
$y
[1] 133native
Единицы не помогли, поскольку они не являются координатами карты. Может быть, мне нужно какое-то преобразование.
Спасибо заранее.
EDIT: (на основе ответа DWin)
У Двина была правильная идея, но коэффициент перевода немного ушел. Помощь с этим будет оценена. В приведенном ниже примере у меня есть карта с красной точкой на ней в координатах (x = -73 и y = 40.855). Я отбросил ответ Dwin в функцию, чтобы вернуть координаты. Я ожидаю, что результаты будут координатами, которые я вставляю, но они не являются.
Идеи?
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
РЕДАКТИРОВАТЬ 2: (Отключение ответа на крещение)
Мы там
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: Функция gglocator
ggmap package теперь содержит эту функциональность.
Я получаю правильный результат, если я добавляю scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
к сюжету, а seekViewport("panel-3-4")
до grid.locator()
Необходимо использовать единую систему, которая имеет смысл и сохраняет информацию в объекте ggplot, чтобы вы могли конвертировать из блоков "npc" в единицы карты:
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
Здесь окончательные результаты, используя все, что DWin и Baptise дали мне завернутый в функцию. Я также запросил список справки ggplot и сообщит вам дополнительную информацию.
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)
Я написал в список справки ggplot и получил очень полезный ответ от Дэвида Келе, которому, похоже, была интересна та же проблема. Его функция отличная:
1) вам не нужно добавлять масштаб y и масштаб x к графику
2) он может сразу найти несколько точек и вернуть их в качестве фрейма данных
3) он работает на любом типе ggplot, а не только на картах
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()
UPDATE: Функция gglocator
ggmap package теперь содержит эту функциональность.
Эти сообщения были очень полезными, но прошло несколько лет, поэтому некоторые вещи были нарушены. Вот несколько новых кодов, которые работают для меня. Код для поиска правильного видового экрана не работал, поэтому вместо current.vpTree()
я использовал ручной поиск нужного окна просмотра, а затем скопировал его в seekViewport()
. Обратите внимание, что для меня был 'panel.6-4-6-4'
, а не старый стиль panel-*
. Наконец, я не получал правильных ответов при рендеринге в rstudio, вместо этого мне пришлось использовать x11()
.
Вот полный пример. Надеюсь, что это будет полезно.
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