通过htmlWidgets onRender()函数添加许多行来绘制

时间:2017-10-08 23:26:34

标签: r ggplot2 plotly htmlwidgets onrender

我试图拍摄一个空白的情节,从htmlWidgets将其输入onRender(),并在onRender()函数中添加许多行。在下面的代码中,我使用了一个包含100行(100行)的数据集,当我运行应用程序时,大约一秒内在onRender()内部绘制了100行。但是,当我将数据集更改为具有2000行时,将全部绘制它们需要十秒钟。

我正在尝试为50,000到100,000行的数据集实现此目的。由于当前代码的缓慢,这显然是有问题的!

我目前正在实现该功能的方式是:

  1. 在R中创建一个名为pcpDat的数据框。它有100行和6列数字数据。
  2. 在R中创建一个名为p
  3. 的空白图
  4. 提供数据框pcpDat并将p绘制到onRender()
  5. 在onRender()中:我有一个xArr对象,它只包含值0,1,2,3,4,5。 对于数据帧的每一行,我将其6个值重建为名为yArr的数值向量。然后,对于数据的每一行,我创建一个Plotly跟踪对象,其中包含要为6 x和6 y值绘制的xArr和yArr。然后,此Plotly跟踪对象为原始数据框的每一行创建一条橙色线。
  6. 绘制这么多线条似乎很愚蠢!我的理由是我试图最终添加功能,以便用户可以使用Plotly选择绘图上的区域并仅查看截取该区域的线条(其余线条将被删除)。这就是为什么我希望这些线条是"交互式的#34;。

    这一切让我思考了几个问题:

    1. 我对JavaScript没有经验(这是onRender()函数的关键)。我想知道是否有可能期望快速绘制50,000到100,000行(在5秒内)?
    2. 如果对(1)的答案是可能的,我正在寻求关于我如何能够加快"我的代码片段如下。没有太多的JavaScript技能,我很难确定花费最多的时间。我可能无法有效地重建这些数据。
    3. 我渴望听到有关此主题的任何建议或意见。谢谢!

      library(plotly)
      library(ggplot2)
      library(shiny)
      library(htmlwidgets)
      library(utils)
      
      ui <- basicPage(
      
        plotlyOutput("plot1")
      )
      
      server <- function(input, output) {
      
        set.seed(3)
        f = function(){1.3*rnorm(100)}
        pcpDat = data.frame(ID = paste0("ID", 1:100), A=f(), B=f(), C=f(), D=f(), E=f(), F=f())
        pcpDat$ID = as.character(pcpDat$ID)
        plotPCP(pcpDat = pcpDat)
      
        colNms <- colnames(pcpDat[, c(2:(ncol(pcpDat)))])
        nVar <- length(colNms)
      
        p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(alpha=0) + xlim(0,(nVar-1)) +ylim(min(pcpDat[,2:(nVar+1)]),max(pcpDat[,2:(nVar+1)])) + xlab("Sample") + ylab("Count")
        gp <- ggplotly(p)
      
        output$plot1 <- renderPlotly({
          gp %>% onRender("
            function(el, x, data) {
      
            var origPcpDat = data.pcpDat
            var pcpDat = data.pcpDat
      
            var Traces = [];
            var dLength = pcpDat.length
            var vLength = data.nVar
            var cNames = data.colNms
      
            xArr = [];
            for (b=0; b<vLength; b++){
            xArr.push(b)
            }
      
            for (a=0; a<dLength; a++){
            yArr = [];
            for (b=0; b<vLength; b++){
            yArr.push(pcpDat[a][cNames[b]]);
            }
            var pcpLine = {
            x: xArr,
            y: yArr,
            mode: 'lines',
            line: {
            color: 'orange',
            width: 1
            },
            opacity: 0.9,
            }
            Traces.push(pcpLine);
            }
            Plotly.addTraces(el.id, Traces);
      }", data = list(pcpDat = pcpDat, nVar = nVar, colNms = colNms))})
      }
      
      shinyApp(ui, server)
      

      编辑: 为了展示我想要做的事情,我要包括3张图片。它们显示了数据中有10行(行)的示例。第一个图像是用户最初看到的图像(所有10行存在)。然后,用户可以使用&#34; Box select&#34;工具和创建一个矩形(灰色)。对于它包含的所有x值,保留在矩形内的任何行都将保留。在该示例的第二图像中,剩余5行。之后,用户可以创建另一个矩形(灰色)。同样,对于它包含的所有x值,保留在矩形内的任何行仍然存在。在此示例的第三个图像中,现在只剩下1行。这3个屏幕截图来自我的功能代码。所以,我确实有一个原型工作。但是,当我添加数千行时,它太慢了。

      enter image description here

      enter image description here

      enter image description here

1 个答案:

答案 0 :(得分:0)

如果您将ggplot情节javascript 翻译为plotly套餐标准,那么您将删除当前的额外步骤和计算。下面的最小示例解决方案:

output$plot1 <- renderPlotly({

  plot_ly(type = "scatter", mode = "markers") %>%
    add_trace(
      x = ~wt,
      y = ~mpg,
      data = mtcars
    ) %>%
    layout(
      xaxis = list(title = "Sample"),
      yaxis = list(title = "Count")
    )

})

enter image description here

要完成隐藏的跟踪,您可以将visible = "legendonly" attrbute设置为跟踪,用户可以打开或关闭这些跟踪。有关详细信息,请参阅以下答案:1&amp; 2

您还可以使用输入被动来限制您发送到数据中的数据量,而不是每次要生成时都提供所有内容。