简体   繁体   English

添加许多行以通过htmlWidgets onRender()函数进行绘图

[英]Adding many lines to plot through htmlWidgets onRender() function

I am trying to take a blank plot, feed it into onRender() from htmlWidgets, and add many lines inside the onRender() function. 我正在尝试绘制一个空白图,将其从htmlWidgets馈入onRender(),并在onRender()函数内添加许多行。 In the code below, I use a dataset with 100 rows (100 lines), and when I run the application, the 100 lines are drawn inside onRender() in about one second. 在下面的代码中,我使用了一个具有100行(100行)的数据集,当我运行该应用程序时,这100行在大约一秒钟的时间内绘制在onRender()中。 However, when I change the dataset to have, say, 2000 lines, it will take ten seconds to draw them all. 但是,当我将数据集更改为具有2000条线时,将全部绘制需要十秒钟。

I am trying to achieve this for datasets on the order of 50,000 to 100,000 lines. 我正在尝试为50,000至100,000行的数据集实现这一目标。 This obviously is problematic due to the slowness of the code currently! 由于当前代码的缓慢,这显然是有问题的!

The way I am currently achieving the functionality is by: 我目前实现该功能的方式是:

  1. Creating a data frame in R called pcpDat. 在R中创建一个名为pcpDat的数据帧。 It has 100 rows and 6 columns of numeric data. 它具有100行和6列数字数据。
  2. Creating a blank plot in R called p 在R中创建一个称为p的空白图
  3. Feeding data frame pcpDat and plot p into onRender() 馈送数据框pcpDat并将p绘制到onRender()中
  4. In onRender(): I have an xArr object that just contains the values 0,1,2,3,4,5. 在onRender()中:我有一个xArr对象,它仅包含值0、1、2、3、4、5。 For each row of the data frame, I reconstruct its 6 values into a numeric vector called yArr. 对于数据帧的每一行,我将其6个值重构为一个称为yArr的数字矢量。 Then, for each row of the data, I create a Plotly trace object that contains xArr and yArr to be plotted for the 6 x and 6 y values. 然后,对于数据的每一行,我创建一个包含xArr和yArr的Plotly跟踪对象,以绘制6 x和6 y值。 This Plotly trace object then creates one orange line for each row of the original data frame. 然后,该Plotly跟踪对象为原始数据帧的每一行创建一条橙色线。

It may seem silly to have so many lines plotted! 绘制这么多线似乎很愚蠢! My reasoning is I am trying to eventually add functionality so a user can use Plotly to select an area on the plot and view only the lines that intercept that area (the rest of the lines will be deleted). 我的推理是我试图最终添加功能,以便用户可以使用Plotly在绘图上选择一个区域并仅查看截取该区域的线(其余线将被删除)。 This is why I want the lines to be "interactive". 这就是为什么我希望这些行是“交互的”。

This all made me ponder a few questions: 这一切使我思考一些问题:

  1. I am not experienced with JavaScript (which is the crux of the onRender() function). 我对JavaScript没有经验(这是onRender()函数的关键)。 I am wondering if it is even possible to expect 50,000 to 100,000 lines to be plotted quickly (within say 5 seconds)? 我想知道是否有可能快速绘制50,000至100,000条线(例如5秒钟内)?
  2. If the answer to (1) is that it should be possible, I am seeking advice on how I can "speed up" my code snippet below. 如果对(1)的回答是应该的,我正在寻求有关如何“加速”以下代码段的建议。 Without much JavaScript skills, it is difficult for me to determine what is costing the most time. 没有太多的JavaScript技能,我很难确定花费最多的时间。 I could be reconstructing that data inefficiently. 我可能会低效地重建数据。

I am eager to hear any advice or opinions on this topic. 我渴望听到有关该主题的任何建议或意见。 Thank you! 谢谢!

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)

EDIT: To demonstrate what I am trying to do, I am including 3 images. 编辑:为了演示我正在尝试做的事情,我包括3张图片。 They show an example where there are 10 rows (lines) in the data. 它们显示了一个示例,其中数据中有10行(行)。 The first image is what the user would see at first (all 10 lines present). 第一张图像是用户最初看到的图像(所有10行都存在)。 Then, the user can use the "Box select" tool and to create a rectangle (gray). 然后,用户可以使用“框选择”工具并创建一个矩形(灰色)。 Any lines that stay inside the rectangle for all x values it contains remains. 对于矩形所包含的所有x值,保留在矩形内的任何行都会保留。 In the second image for this example, 5 lines remain. 在此示例的第二个图像中,剩下5行。 After that, the user can, say, create another rectangle (gray). 之后,用户可以说创建另一个矩形(灰色)。 Again, any lines that stay inside the rectangle for all x values it contains remains. 同样,对于矩形中包含的所有x值,任何保留在矩形内的线都将保留。 In the third image for this example, only 1 of the lines now remains. 在此示例的第三个图像中,现在仅保留了其中的一行。 These 3 screenshots are from my functioning code. 这3个屏幕截图来自我的功能代码。 So, I do have a prototype working. 因此,我确实有一个原型正在工作。 However, when I add thousands of lines, it is too slow. 但是,当我添加数千行时,它太慢了。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

If you translate your ggplot and plotly javascript to the plotly package standard then you will remove the extra steps and computation you currently have. 如果您将ggplotplotly javascript转换为plotly软件包标准,则将删除当前拥有的多余步骤和计算。 Minimal example solution below: 下面的最小示例解决方案:

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")
    )

})

在此处输入图片说明

To accomplish the hidden traces, you can set the visible = "legendonly" attrbute to your traces, and the user can switch those on or off. 要完成隐藏的痕迹,可以将visible = "legendonly"属性设置为痕迹,用户可以打开或关闭这些痕迹。 See these answers for more detail, 1 & 2 有关更多详细信息,请参见这些答案12

You can also use inputs and reactives to limit the amount of data you send to plotly instead of giving it everything each time you want to generate. 您也可以使用输入反应式来限制发送给您的数据量,而不是每次提供要生成的所有内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在htmlWidgets的onRender()函数中使用Shiny actionButton()函数 - Using Shiny actionButton() function in onRender() function of htmlWidgets 保存在htmlWidgets中的onRender()函数中创建的对象 - Save object created in onRender() function in htmlWidgets 对htmlWidgets的onRender()函数中的Javascript代码进行故障排除 - Troubleshoot Javascript code in onRender() function of htmlWidgets 我使用 htmlwidgets::onRender 将数字添加到 sankey 网络,但将 plot 保存为 png 后似乎没有出现数字 - I used htmlwidgets::onRender to add numbers to a sankey network, but the numbers do not seem to be appear after saving the plot as png 每次用户在onRender htmlwidget中进行交互时,删除旧跟踪并添加新跟踪 - Removing old trace and adding new trace each time user interacts in onRender htmlwidgets 使用 htmlwidgets::onRender() 应用 JScode 删除视图框时,通过 renderUI 的 sankeyNetwork 消失 - sankeyNetwork through renderUI disappears when applying JScode to remove viewbox with htmlwidgets::onRender() 有效的方法来修改htmlWidgets的onRender()中的选定点 - Efficient way to modify selected points in onRender() of htmlWidgets 在R中的onRender()htmlWidgets上更改散点图中的线宽和不透明度 - Changing line thickness and opacity in scatterplot on onRender() htmlWidgets in R 在步骤 function 的 plot 中添加水平线 - Adding horizontal lines in the plot of a step function 在绘图线上加数字 - adding numbers on the lines of a plot
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM