我正在尝试绘制一个空白图,将其从 htmlWidgets 输入 onRender(),并在 onRender() 函数中添加许多行。在下面的代码中,我使用了一个包含 100 行(100 行)的数据集,当我运行应用程序时,大约一秒钟内就会在 onRender() 中绘制 100 行。但是,当我将数据集更改为具有 2000 行时,需要十秒钟才能将它们全部绘制出来。
我试图为 50,000 到 100,000 行的数据集实现这一点。由于当前代码的缓慢,这显然是有问题的!
我目前实现该功能的方式是:
- 在 R 中创建一个名为 pcpDat 的数据框。它有 100 行和 6 列的数值数据。
- 在 R 中创建一个名为 p 的空白图
- 将数据框 pcpDat 和绘图 p 输入 onRender()
- 在 onRender() 中:我有一个 xArr 对象,它只包含值 0、1、2、3、4、5。对于数据帧的每一行,我将其 6 个值重构为一个名为 yArr 的数字向量。然后,对于数据的每一行,我创建一个 Plotly 跟踪对象,其中包含要绘制的 6 个 x 和 6 个 y 值的 xArr 和 yArr。然后,此 Plotly 跟踪对象为原始数据框的每一行创建一条橙色线。
绘制这么多行似乎很愚蠢!我的理由是我试图最终添加功能,以便用户可以使用 Plotly 选择绘图上的一个区域并仅查看拦截该区域的线(其余的线将被删除)。这就是为什么我希望这些线条是“交互式的”。
这一切让我思考了几个问题:
- 我对 JavaScript 没有经验(这是 onRender() 函数的关键)。我想知道是否有可能期望快速绘制 50,000 到 100,000 条线(比如说 5 秒内)?
- 如果 (1) 的答案应该是可能的,我正在就如何“加快”下面的代码片段寻求建议。如果没有太多的 JavaScript 技能,我很难确定什么是最耗时的。我可能无法有效地重建这些数据。
我渴望听到有关此主题的任何建议或意见。谢谢!
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 行都存在)。然后,用户可以使用“框选”工具来创建一个矩形(灰色)。对于它包含的所有 x 值,留在矩形内的任何线都将保留。在此示例的第二张图像中,剩余 5 行。之后,用户可以创建另一个矩形(灰色)。同样,对于它包含的所有 x 值,保留在矩形内的任何行都将保留。在此示例的第三张图像中,现在只剩下 1 行。这 3 个屏幕截图来自我的功能代码。所以,我确实有一个原型工作。但是,当我添加数千行时,它太慢了。