【问题标题】:Update large plots in Shiny without Re-Rendering在 Shiny 中更新大图而不重新渲染
【发布时间】:2016-12-19 23:44:50
【问题描述】:

总体目标

我希望能够使用 RShiny 快速绘制来自 R 的大量数据,然后进行小的修改或添加,而无需重新渲染所有绘制的数据。

具体任务

  1. 在散点图中绘制大量点 (
  2. 响应鼠标点击,检测最近的绘图点。
  3. 使用从与该点相关的数据中查询到的一些信息,突出显示少量其他点 (

当前方法

我目前使用 ggplot2 和 RShiny 制作应用程序来帮助进行数据分析。总的来说,我对这种组合非常满意。因此,理想情况下,该解决方案将允许我仍然主要使用这些工具。

仅使用 RShiny 和 ggplot2 的内置功能,我完成任务没有问题,除了步骤 3 不能独立完成,无需重做步骤 1。据我了解如果不完全重新渲染它们,就无法更新或覆盖 ggplot2 图。

因此,我正在寻找以下其中一项来实现我的总体目标,按偏好降序排列:

  1. 一种无需重新渲染即可覆盖或修改 ggplot2 图的方法。
  2. 允许此操作的基于 ggplot2 的扩展或 fork 或类似 R。
  3. ggplot2 的替代方案,同样易于与允许此操作的 RShiny 和 R 数据集成。也许是现有 javascript 库的某个接口?我仍然希望能够使用我熟悉的所有 RShiny 机器来操纵我的情节并与之互动。

我对 js 有一些了解,但不想学习 d3 之类的东西来完成这么小的任务。 (如果可以使用少量的 d3 或 js 来做到这一点,那就太好了!)能够在 ggplot2 绘图上有效地绘制 svg 会很好,但使用相同的坐标系。

我知道this question,但提供的解决方案是针对时间序列数据的。

【问题讨论】:

  • 你看过plotly吗?它有一些交互性。还有ggvis,不过还真没写完——很明显。
  • 我简要地看了看。我的印象是 ggplotly 函数在完成第 1 步时要慢得多。如果有一种方法可以以某种精简的方式将 R 与 plotly 一起使用,那可能会很好。我对 ggvis 不熟悉,可能就是这个问题。
  • ggvis 是 Hadley Wickam 的下一个大作,应该为 ggplot 添加交互性。不幸的是,这需要比他最初想象的更多的重组,因此比最初宣布的时间要长一两年。
  • 您也可以直接在带有网格的 ggplot 输出上绘制。但这并不容易,关于各种坐标系和布局的文档充其量也很少(大多数情况下您需要查看代码才能弄清楚)。
  • 所以看看 ggplot2 的 github 源代码(它不是你常用的 R 代码)。特别是看看来自 github 用户 baptiste 的 gridExtra 库。在那个库中,你会看到很多你需要理解的东西。

标签: javascript r ggplot2 shiny


【解决方案1】:

这是plotly 的解决方案。它确实会重新渲染整个情节,但速度很快,因此也许仍能满足您的要求。我想您会发现,引入 Plotly 不会严重影响您的工作流程。

请注意,我使用 Plotly 的 WebGL function 来提高速度。下面的例子是 100000 点。我还提供了一个示例,说明如何转换现有的ggplot2object。对于 Plotly 点击事件,see this

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

ui <- fluidPage(

  titlePanel("Highlight nearby points"),

  sidebarLayout(
    sidebarPanel(width=3,
      p("Click on a point. Nearby points will be highlighted.")
    ),

    mainPanel(
      plotlyOutput("plot")
    )
  )
)

# Data
df <- tibble(x = runif(1e+05,1,100), y = runif(1e+05,1,100))

server <- function(input, output, session) {

  output$plot <- renderPlotly({

    # Gather click data
    event.data <- event_data("plotly_click")

    # Plotly object
    p <- plot_ly(df, x = ~x, y = ~y, type = "scatter", mode = "markers") 

    # Alternative: use existing ggplot

    # gg <- ggplot(df, aes(x = x, y = y)) +
    #   geom_point()
    # 
    # p <- plotly_build(gg)

    # End alternative

    # Check for click data
    if(!is.null(event.data)) {

      # If click data exists, create new markers based on range criteria and use a different color
      d <- filter(df,
                  x < event.data$x+10 & x > event.data$x-10,
                  y < event.data$y+10 & y > event.data$y-10)
      p <- add_markers(p, data = d, color = I("red"))

    }

    # Use webGL for faster ploting of many points
    p %>% toWebGL()

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

【讨论】:

  • 我非常感谢您的努力,但至少对我来说,这个解决方案的性能比没有情节的相同解决方案差。如果情节仍然需要重建情节,我看不出它的用途对我的问题有什么影响。
  • @mb7744 有趣的是,它实际上对我来说有点慢。好的,我会再考虑一下,但我不确定如何在不重新渲染的情况下输出绘图对象。您需要使渲染对象无效才能更新输出。这样做时,它将运行渲染中的所有代码。
猜你喜欢
  • 2013-08-22
  • 2020-12-14
  • 2020-12-13
  • 2021-10-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2016-12-30
  • 2020-11-20
相关资源
最近更新 更多