1

我正在尝试创建一个应用程序,如果用户在 Plotly 中使用 Box Select 工具,那么 Box Select 旁边将出现一个填充的矩形。为此,我试图调用 Plotly.addTrace() 来创建一个矩形对象(类型:rect),该对象具有用户选择的框的角。

我能够获得用户选择的框角的坐标(在代码中它们被称为 xMin、xMax、yMin 和 yMax)。但是,然后我尝试创建一个名为 drawRect 的变量,该变量可以添加到 Plotly 中。不过,此时这无济于事。

我基于一篇关于 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)
4

1 回答 1

0

基本上,对我们这些老兽医来说可能听起来很奇怪ggplot,“形状”的处理方式与标记和线条(设置在“痕迹”中)不同,但“形状”(如矩形)设置在layouta 的一部分中情节。如果我阅读更多的情节书,我可能会更好地理解这一点。

所以我做了两个改变。

  • 在开始时将其更改dragmode"select"使用layout
  • 将javascriptPlotly.addTraces末尾的逻辑更改为onRenderPlotly.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)

这是它工作的屏幕截图:

在此处输入图像描述

于 2017-04-06T15:56:58.020 回答