在没有重新渲染的情况下更新Shiny中的大图 [英] Update large plots in Shiny without Re-Rendering

查看:157
本文介绍了在没有重新渲染的情况下更新Shiny中的大图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

总体目标



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

特定任务


  1. 绘制散点图中的大量点(< 100 000)。我可以在短时间(<5秒)内完成这项工作,但可以感知延迟。

  2. 响应鼠标点击,检测最近的绘图点。
  3. 使用从与此点相关的数据查询的一些信息,突出显示少量其他点(< 10)。

目前的做法

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



仅使用RShiny和ggplot2的内置功能,完成我的任务并不困难,除了之外,第3步不能独立完成,不需要重做第1步。我的理解是,无法更新或覆盖ggplot2图,而无需全部重新渲染它们。



因此,我在寻找的是以下优先顺序之一:按照优先级的降序顺序实现我的总体目标:


  1. 一种覆盖或修改ggplot2图的方法,不需要重新渲染。
  2. 一个扩展名或者fork或者类似的基于R的ggplot2允许这样做。

  3. ggplot2的另一种选择,同样可以很容易地与RShiny和R数据集成,这可以实现这一点。也许一个现有的JavaScript库的一些接口?我仍然希望能够使用我熟悉的所有RShiny机器来操作和与我的情节进行交互。

我有一些关于js的知识,但不喜欢学习像d3这样的东西来完成这样一个小任务。 (如果可以使用一小部分d3或js来做到这一点,那就太棒了)。能够在ggplot2图上有效地绘制svg会很好,但是使用相同的坐标系。 p>

我知道这个问题,但是提供的解决方案是特定于时间序列数据的。

解决方案

以下是 plotly 的解决方案。它会重新渲染整个剧情,但速度很快,所以可能仍然会满足您的要求。我想你会发现引入Plotly应该不会大大破坏你的工作流程。



请注意,我使用Plotly的 WebGL功能以获得速度。下面的例子是100000点。我还包括了一个如何转换现有的 ggplot2 对象的例子。对于单击事件,查看

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

$ u $< - fluidPage(

titlePanel(Highlight highlight points),

sidebarLayout(
sidebarPanel(width = 3,
p( )
),

mainPanel(
plotlyOutput(plot)



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

服务器< - 函数(输入,输出,会话){

输出$ plot< - renderPlotly({

#收集点击数据
event.data< - event_data(plotly_click)

#绘图对象
p < - plot_ly(df,x =〜x,y =〜y,type =scatter, mode =markers)

#可选:使用现有的ggplot

#gg < - ggp lot(df,aes(x = x,y = y))+
#geom_point()

#p < - plotly_build(gg)

#结束替代

#检查点击数据
if(!is.null(event.data)){

#如果点击数据存在,创建新标记基于范围标准并使用不同的颜色
d< - 过滤器(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))

}

#使用webGL快速绘制多个点
p%>%到webGL()

))
}

#运行应用程序
shinyApp(ui = ui,server = server)


General Goal

I would like to be able to use RShiny to quickly plot large amounts of data that comes from R, and then make small modifications or additions without re-rendering all of the plotted data.

Specific Task

  1. Plot a large number of points (<100 000) in a scatter plot. I am okay with a short (<5 sec) but perceivable delay in this task.
  2. In response to a mouse click, detect the nearest plotted point.
  3. Using some information queried from data related to this point, highlight a small number of other points (<10). I would like this to be instantaneous.

Current Approach

I currently use ggplot2 and RShiny to make apps to help with data analysis. In general I'm very pleased with this combination. So ideally the solution will allow me to still mostly use these tools.

Using only the built-in functionality of RShiny and ggplot2, I have no problem accomplishing my task, except that step 3 cannot be done independently, without redoing step 1. It is my understanding that it is not possible to update or overlay ggplot2 plots without re-rendering them in their entirety.

So, what I am looking for is one of the following to achieve my general goal, in descending order of preference:

  1. A way to overlay or modify ggplot2 plots without re-rendering.
  2. An extension or fork or similar R-based to ggplot2 that allows this.
  3. An alternative to ggplot2 that is similarly easy to integrate with RShiny and R data that can allow this. Maybe an some interface to an existing javascript library? I would still like to be able to manipulate and interact with my plot using all of the RShiny machinery I am familiar with.

I have some knowledge of js but do not feel like learning something like d3 to accomplish such a small task. (If it's possible to use a small bit of d3 or js to do this, that would be great though!) It would be fine to be able to efficiently draw svg on top of ggplot2 plots, but using the same coordinate system.

I am aware of this question, but the solution provided was specific to time-series data.

解决方案

Here is a solution with plotly. It does re-render the entire plot, but it's fast so perhaps will still meet your requirements. I think you'll see that introducing Plotly should not majorly disrupt your workflow.

Note that I use Plotly's WebGL function for speed. The example below is 100000 points. I've also included an example of how you would convert your existing ggplot2object. For Plotly click events, 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)

这篇关于在没有重新渲染的情况下更新Shiny中的大图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆