Блестящий щелчок/кисть не работает с недекартовыми координатами?

Я работаю над приложением Shiny, которое должно позволить пользователю выбирать точки географических данных на карте мира, созданной ggplot2 (как в этот пример).

Это работает, если я использую обычную систему координат coord_cartesian (которая искажает карты), но не работает, если я использую более подходящую систему координат coord_map. Похоже, что события щелчка/кисти не получают правильные координаты после проекции. Есть ли способ обойти или исправить это, не возвращаясь к декартовым координатам?

Вы можете найти рабочий пример ниже:

library(shiny)
library(ggplot2)
library(dplyr)

map_world <- function(world, mapPoints, xlim, ylim){
  # function to generate ggplot world map
  ggplot() + 
    geom_polygon(data=world, aes(x=long, y=lat, group=group)) +
    geom_point(data=mapPoints, aes(x=Longitude, y=Latitude), color="red") +
    # coord_map messes up the brush select
     coord_map(xlim=xlim, ylim=ylim)
    # coord_cartesian would work but distort the map
    # coord_cartesian(xlim=xlim, ylim=ylim)
}

mapPoints <- data.frame(Longitude=c(-103, -108, -130, -120),
                      Latitude=c(52, 40, 45, 54))
world <- map_data("world")

ui <- fluidPage(
  fluidRow(
    column(width = 6, 
           plotOutput("plot1", height = 300, 
                      click = "plot1_click", brush = "plot1_brush") )
  ),
  fluidRow(
    column(width = 6, 
           h4("Near points"), verbatimTextOutput("click_info") ),
    column(width = 6, 
           h4("Brushed points"), verbatimTextOutput("brush_info") )
  )
)

server <- function(input, output) {
  # output world map
  output$plot1 <- renderPlot({
    map_world(world = world, mapPoints = mapPoints, 
              xlim=c(-180,180), ylim=c(-90,90))
  })
  # output clicked points 
  output$click_info <- renderPrint({
    nearPoints(mapPoints, xvar="Longitude", 
                  yvar="Latitude", input$plot1_click)
  })
  # output brushed points 
  output$brush_info <- renderPrint({
    brushedPoints(mapPoints, xvar="Longitude", 
                  yvar="Latitude", input$plot1_brush)
  })
}

shinyApp(ui, server)

Спасибо!


person Mariana Oliveira    schedule 06.08.2016    source источник


Ответы (1)


Я пробовал некоторые решения с использованием ggplot, но есть проблема с масштабированием, которое не улавливается функцией plotOutput. На странице справки (http://shiny.rstudio.com/reference/shiny/latest/plotOutput.html), обратите внимание на следующее:

Для plotOutput координаты будут отправлены в масштабе пространства данных, если это возможно. (В настоящее время графики, сгенерированные базовой графикой и ggplot2, поддерживают это масштабирование, хотя графики, сгенерированные решеткой и другими, этого не делают.) Если масштабирование невозможно, будут отправлены необработанные координаты пикселей. Для imageOutput координаты будут отправлены в необработанных пиксельных координатах.

также,

С графикой ggplot2 код в renderPlot должен возвращать объект ggplot; если вместо этого код печатает объект ggplot2 с чем-то вроде print(p), то координаты для интерактивной графики не будут должным образом масштабироваться в пространстве данных.

Я попытался переместить ggplot в серверную часть скрипта, но это не сработало.

Мое предлагаемое решение, используйте базовую графику:

library(shiny)
library(dplyr)
library(maps)
library(mapdata)


mapPoints <- data.frame(Longitude=c(-103, -108, -130, -120),
                        Latitude=c(52, 40, 45, 54))

ui <- fluidPage(
  fluidRow(
    column(width = 6, 
           plotOutput("plot1", height = 300, 
                      click = "plot1_click", brush = "plot1_brush") )
  ),
  fluidRow(
    column(width = 6, 
           h4("Near points"), verbatimTextOutput("click_info") ),
    column(width = 6, 
           h4("Brushed points"), verbatimTextOutput("brush_info") )
  )
)

server <- function(input, output) {
  # output world map
  output$plot1 <- renderPlot({
    map('worldHires')
    points(mapPoints$Longitude, mapPoints$Latitude, 
           col = "red", pch = 16)
  })
  # output clicked points 
  output$click_info <- renderPrint({
    nearPoints(mapPoints, xvar="Longitude", 
               yvar="Latitude", input$plot1_click)
  })
  # output brushed points 
  output$brush_info <- renderPrint({
    brushedPoints(mapPoints, xvar="Longitude", 
                  yvar="Latitude", input$plot1_brush)
  })
}

shinyApp(ui, server)
person donlelek    schedule 10.08.2016
comment
Спасибо, это работает! Тем не менее, ggplot2 позволил мне получить данные о мире только один раз, и это казалось более быстрым для рендеринга (этот пример я включаю более одного раза в более крупное приложение). Я думаю, что базовая графика не позволит мне сохранить слой карты мира для потом. Можете ли вы придумать способ сократить время, необходимое для создания карты? Спасибо еще раз. - person Mariana Oliveira; 10.08.2016
comment
По сути, это то же самое, что и исходная версия ggplot без coord_map, так что вы можете использовать исходный код. - person wch; 10.08.2016
comment
На самом деле он ведет себя по-другому. Вот что я получаю с base по сравнению с ggplot2 (точки выбираются из заштрихованной области на карте справа). Base изменяет масштаб осей, а ggplot2 — нет, создавая больше искажений (ранее сегодня я представил проблему блестящей команде на github). - person Mariana Oliveira; 10.08.2016
comment
Привет @MarianaOliveira, я думаю, что один из способов повысить скорость — это использовать карту с более низким разрешением, то есть map('world') (из пакета карты) вместо map('worldHires') (из пакета mapdata). Кроме того, функция map принимает аргумент resolution, или вы можете указать свои собственные полигоны для map в аргументе database. Надеюсь, это поможет, но я все еще озадачен поведением ggplot. Наконец, для интерактивных карт, возможно, обратите внимание на другие варианты, такие как листовка. - person donlelek; 11.08.2016
comment
Спасибо, это полезные советы! Я взглянул на буклет, но мне показалось, что будет сложнее позволить пользователю выбрать интересующий его географический регион (я не думаю, что у него есть опция кисти, не так ли?). Вы можете взглянуть на проблему, которую я поднял на github относительно поведения ggplot2 (это похоже, что это связано с еще одной открытой проблемой). - person Mariana Oliveira; 11.08.2016
comment
Взгляните на блестящий пример SuperZip, листовка зависит от масштабирования вашей области. интерес, а не чистить его. Ваше здоровье! - person donlelek; 11.08.2016