【问题标题】:Shiny click/brush not working with non-cartesian coordinates?闪亮的点击/画笔不适用于非笛卡尔坐标?
【发布时间】:2016-08-06 16:40:36
【问题描述】:

我正在开发一个 Shiny 应用程序,它应该让用户在 ggplot2 生成的世界地图上选择地理数据点(如 this example)。

如果我使用常规的 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)

谢谢!

【问题讨论】:

    标签: r ggplot2 shiny coordinate-systems brush


    【解决方案1】:

    我尝试了一些使用ggplot 的解决方案,但是plotOutput 函数没有拾取缩放存在一些问题。在帮助页面 (http://shiny.rstudio.com/reference/shiny/latest/plotOutput.html) 中,请注意以下几点:

    对于plotOutput,如果可能,坐标将按比例发送到数据空间。 (目前,基本图形和 ggplot2 生成的绘图支持这种缩放,尽管 lattice 和其他生成的绘图不支持。)如果无法缩放,将发送原始像素坐标。对于imageOutput,坐标将以原始像素坐标发送。

    还有,

    使用 ggplot2 图形,renderPlot 中的代码应该返回一个 ggplot 对象;如果代码使用print(p) 之类的东西打印 ggplot2 对象,则交互式图形的坐标将无法正确缩放到数据空间。

    我尝试将 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)
    

    【讨论】:

    • 谢谢,这行得通!但是,ggplot2 只允许我获取世界数据一次,而且渲染速度似乎更快(这个例子是我在一个更大的应用程序中不止一次包含的东西)。我认为基本图形不会让我保存世界地图图层之后。您能想出一种方法来缩短生成地图所需的时间吗?再次感谢。
    • 这与不使用coord_map 的原始ggplot 版本基本相同,因此您不妨使用原始代码。
    • 它实际上似乎表现不同。这是我使用baseggplot2 得到的结果(点是从右侧地图上的刷区域中选择的)。 Base 会重新缩放轴,而 ggplot2 不会,造成更多失真(我今天早些时候将问题提交给了 github 的闪亮团队)。
    • 嗨@MarianaOliveira,我认为可以提高速度的一种方法是使用较低分辨率的地图,即map('world')(来自地图包)而不是map('worldHires')(来自地图数据包)。此外,map 函数接受 resolution 参数,或者您可以在 database 参数中将自己的多边形提供给 map。我希望这会有所帮助,但我仍然对 ggplot 的行为感到困惑。最后,对于交互式地图,不妨看看传单等其他选项。
    • 谢谢,这些建议很有用!我看过传单,但似乎让用户在那里选择感兴趣的地理区域会更难(我认为它没有画笔选项,是吗?)。你可以看看我在 github 上提出的关于 ggplot2 行为的issue(似乎与another open issue 有关)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 2017-11-27
    • 1970-01-01
    相关资源
    最近更新 更多