在 Plotly R 中添加带 select 框角的阴影矩形
Add shaded rectangle with select Box corners in Plotly R
我正在尝试创建一个应用程序,如果用户在 Plotly 中使用方框 Select 工具,那么方框 Select 旁边会出现一个填充的矩形。为此,我试图调用 Plotly.addTrace() 来创建一个矩形对象(类型:rect),该对象具有用户选择的框的角。
我能够获取用户选择的方框角的坐标(在代码中它们称为 xMin、xMax、yMin 和 yMax)。但是,我随后尝试创建一个名为 drawRect 的变量,该变量可以添加到 Plotly。不过,此时这没有任何作用。
我基于 post 关于 Python Plotly (https://plot.ly/python/shapes/) 的一些语法。但是,我在 R 中使用 Plotly。是否有任何类似的矩形对象可以在 Plotly R 中使用?
下面是 MWE 显示我的代码。
library(ggplot2)
library(shiny)
library(plotly)
library(htmlwidgets)
ui <- basicPage(
plotlyOutput("plot1")
)
server <- function(input, output) {
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(alpha=0) + xlim(0,5) +ylim(-3,3)
gp <- ggplotly(p)
set.seed(3)
myDF <- data.frame(X1=rnorm(10,-1), X2=rnorm(10,-1), X3=rnorm(10,-1), X4=rnorm(10,1), X5=rnorm(10,1), X6=rnorm(10,1))
colNms <- colnames(myDF)
nVar <- length(colNms)
output$plot1 <- renderPlotly({
gp %>% onRender("
function(el, x, data) {
var myDF = data.myDF
var Traces = [];
var dLength = myDF.length
var vLength = data.nVar
var cNames = data.colNms
for (a=0; a<dLength; a++){
xArr = [];
yArr = [];
for (b=0; b<vLength; b++){
xArr.push(b)
yArr.push(myDF[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);
el.on('plotly_selected', function(e) {
var dLength = myDF.length
var selectedPCP = []
var xMin = e.range.x[0]
var xMax = e.range.x[1]
var yMin = e.range.y[0]
var yMax = e.range.y[1]
console.log([xMin, xMax, yMin, yMax])
var Traces = []
var drawRect = {
type: 'rect',
x0: xMin,
y0: yMin,
x1: xMax,
y1: yMax,
line: {
color: 'green',
width: 1
},
fillcolor: 'green'
}
Traces.push(drawRect);
Plotly.addTraces(el.id, Traces);
})
}", data = list(myDF = myDF, nVar = nVar, colNms = colNms))})
}
shinyApp(ui, server)
基本上,虽然对我们这些老 ggplot
老手来说听起来很奇怪,但 "shapes" 的处理方式与标记和线条(在 "traces" 中设置)不同,但是"shapes"(如 rect)设置在 plotly plot 的 layout
部分。如果我读更多的情节书,我可能会更好地理解这一点..
所以我做了两个改变。
- 在开头使用
layout
将 dragmode
更改为 "select"
。
- 将
onRender
javascript 末尾的 Plotly.addTraces
逻辑更改为 Plotly.relayout
作为旁注,几个小时以来我一直在想为什么它被称为 "relay-out",我在写这篇文章时才意识到它是 "re-layout",这是完全有道理的。
代码如下:
library(ggplot2)
library(shiny)
library(plotly)
library(htmlwidgets)
ui <- basicPage(
plotlyOutput("plot1")
)
server <- function(input, output) {
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(alpha=0) + xlim(0,5) +ylim(-3,3)
gp <- ggplotly(p)
set.seed(3)
myDF <- data.frame(X1=rnorm(10,-1), X2=rnorm(10,-1), X3=rnorm(10,-1), X4=rnorm(10,1), X5=rnorm(10,1), X6=rnorm(10,1))
colNms <- colnames(myDF)
nVar <- length(colNms)
output$plot1 <- renderPlotly({
gp %>% layout(dragmode="select") %>%
onRender("
function(el, x, data) {
var myDF = data.myDF
var Traces = [];
var dLength = myDF.length
var vLength = data.nVar
var cNames = data.colNms
for (a=0; a<dLength; a++){
xArr = [];
yArr = [];
for (b=0; b<vLength; b++){
xArr.push(b)
yArr.push(myDF[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);
el.on('plotly_selected', function(e) {
var dLength = myDF.length
var selectedPCP = []
var xMin = e.range.x[0]
var xMax = e.range.x[1]
var yMin = e.range.y[0]
var yMax = e.range.y[1]
console.log([xMin, xMax, yMin, yMax])
var Traces = []
var drawRect = {
type: 'rect',
x0: xMin,
y0: yMin,
x1: xMax,
y1: yMax,
line: {
color: 'green',
width: 1
},
fillcolor: 'green'
}
var update = {
shapes:[drawRect]
}
Plotly.relayout(el.id, update)
})
}", data = list(myDF = myDF, nVar = nVar, colNms = colNms))})
}
shinyApp(ui, server)
这是它工作的屏幕截图:
我正在尝试创建一个应用程序,如果用户在 Plotly 中使用方框 Select 工具,那么方框 Select 旁边会出现一个填充的矩形。为此,我试图调用 Plotly.addTrace() 来创建一个矩形对象(类型:rect),该对象具有用户选择的框的角。
我能够获取用户选择的方框角的坐标(在代码中它们称为 xMin、xMax、yMin 和 yMax)。但是,我随后尝试创建一个名为 drawRect 的变量,该变量可以添加到 Plotly。不过,此时这没有任何作用。
我基于 post 关于 Python Plotly (https://plot.ly/python/shapes/) 的一些语法。但是,我在 R 中使用 Plotly。是否有任何类似的矩形对象可以在 Plotly R 中使用?
下面是 MWE 显示我的代码。
library(ggplot2)
library(shiny)
library(plotly)
library(htmlwidgets)
ui <- basicPage(
plotlyOutput("plot1")
)
server <- function(input, output) {
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(alpha=0) + xlim(0,5) +ylim(-3,3)
gp <- ggplotly(p)
set.seed(3)
myDF <- data.frame(X1=rnorm(10,-1), X2=rnorm(10,-1), X3=rnorm(10,-1), X4=rnorm(10,1), X5=rnorm(10,1), X6=rnorm(10,1))
colNms <- colnames(myDF)
nVar <- length(colNms)
output$plot1 <- renderPlotly({
gp %>% onRender("
function(el, x, data) {
var myDF = data.myDF
var Traces = [];
var dLength = myDF.length
var vLength = data.nVar
var cNames = data.colNms
for (a=0; a<dLength; a++){
xArr = [];
yArr = [];
for (b=0; b<vLength; b++){
xArr.push(b)
yArr.push(myDF[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);
el.on('plotly_selected', function(e) {
var dLength = myDF.length
var selectedPCP = []
var xMin = e.range.x[0]
var xMax = e.range.x[1]
var yMin = e.range.y[0]
var yMax = e.range.y[1]
console.log([xMin, xMax, yMin, yMax])
var Traces = []
var drawRect = {
type: 'rect',
x0: xMin,
y0: yMin,
x1: xMax,
y1: yMax,
line: {
color: 'green',
width: 1
},
fillcolor: 'green'
}
Traces.push(drawRect);
Plotly.addTraces(el.id, Traces);
})
}", data = list(myDF = myDF, nVar = nVar, colNms = colNms))})
}
shinyApp(ui, server)
基本上,虽然对我们这些老 ggplot
老手来说听起来很奇怪,但 "shapes" 的处理方式与标记和线条(在 "traces" 中设置)不同,但是"shapes"(如 rect)设置在 plotly plot 的 layout
部分。如果我读更多的情节书,我可能会更好地理解这一点..
所以我做了两个改变。
- 在开头使用
layout
将dragmode
更改为"select"
。 - 将
onRender
javascript 末尾的Plotly.addTraces
逻辑更改为Plotly.relayout
作为旁注,几个小时以来我一直在想为什么它被称为 "relay-out",我在写这篇文章时才意识到它是 "re-layout",这是完全有道理的。
代码如下:
library(ggplot2)
library(shiny)
library(plotly)
library(htmlwidgets)
ui <- basicPage(
plotlyOutput("plot1")
)
server <- function(input, output) {
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(alpha=0) + xlim(0,5) +ylim(-3,3)
gp <- ggplotly(p)
set.seed(3)
myDF <- data.frame(X1=rnorm(10,-1), X2=rnorm(10,-1), X3=rnorm(10,-1), X4=rnorm(10,1), X5=rnorm(10,1), X6=rnorm(10,1))
colNms <- colnames(myDF)
nVar <- length(colNms)
output$plot1 <- renderPlotly({
gp %>% layout(dragmode="select") %>%
onRender("
function(el, x, data) {
var myDF = data.myDF
var Traces = [];
var dLength = myDF.length
var vLength = data.nVar
var cNames = data.colNms
for (a=0; a<dLength; a++){
xArr = [];
yArr = [];
for (b=0; b<vLength; b++){
xArr.push(b)
yArr.push(myDF[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);
el.on('plotly_selected', function(e) {
var dLength = myDF.length
var selectedPCP = []
var xMin = e.range.x[0]
var xMax = e.range.x[1]
var yMin = e.range.y[0]
var yMax = e.range.y[1]
console.log([xMin, xMax, yMin, yMax])
var Traces = []
var drawRect = {
type: 'rect',
x0: xMin,
y0: yMin,
x1: xMax,
y1: yMax,
line: {
color: 'green',
width: 1
},
fillcolor: 'green'
}
var update = {
shapes:[drawRect]
}
Plotly.relayout(el.id, update)
})
}", data = list(myDF = myDF, nVar = nVar, colNms = colNms))})
}
shinyApp(ui, server)
这是它工作的屏幕截图: