[英]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: 我目前实现该功能的方式是:
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: 这一切使我思考一些问题:
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. 如果您将ggplot
和plotly 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 有关更多详细信息,请参见这些答案1和2
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.