处理后从 plotly select 中清除 event_data

Clear event_data from plotly select after processing it

在下面的虚拟应用程序中,用户可以通过拖动 1 个或多个点周围的区域来 select / deselect 个点。 这导致这些点的状态从 data.table 中的 T <-> F 翻转。

我现在想解决的是event_data处理后如何清空,

或者至少确保用户可以 select 同一组点连续两次。

即:现在,select将底部的三个点变成十字, select使用相同的三个点并打算将它们转回圆圈目前不起作用,因为 event_data 与之前的 selection 相同。

我以为我成功了,但事实证明我没有。

Plotly 允许通过双击清除事件数据,但我想通过代码中的自动功能实现同样的效果,以便在事件数据出现时立即清除处理。 我也尝试过使用此解决方案来处理点击事件,但我无法将其用于我的 select 事件

  useShinyjs(),

    extendShinyjs(text = "shinyjs.resetSelect = function() { Shiny.onInputChange('.clientValue-plotly_click-A', 'null'); }"),

在 UI 和 js$resetSelect() 在服务器块中

GIF 显示了在拖动 select 操作之间双击和不双击行为之间的差异。

library(shiny)
library(plotly)
library(dplyr)
library(data.table)

testDF <- data.table( MeanDecreaseAccuracy =  runif(10, min = 0, max = 1), Variables = letters[1:10])
testDF$Selected <- T

ui <- fluidPage(
  plotlyOutput('RFAcc_FP1',  width = 450)
)

server <- function(input, output, session) {

  values <- reactiveValues(RFImp_FP1 = testDF)

  observe({
    if(!is.null( values$RFImp_FP1)) {
      values$Selected <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
    }
  })


  observeEvent(values$Selected, {
    parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
    if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
      data_df <- values$RFImp_FP1
      data_df <- data_df %>% .[, Selected := if_else(Variables %in% parsToChange, !Selected, Selected)]
      values$RFImp_FP1 <- NULL
      values$RFImp_FP1 <- data_df
    }

  })


  output$RFAcc_FP1 <- renderPlotly({

    RFImp_score <- values$RFImp_FP1[order(MeanDecreaseAccuracy)]
    plotheight <- length(RFImp_score$Variables) * 80
    colors <- if(length(unique(RFImp_score$Selected)) > 1) { c('#F0F0F0', '#1b73c1') } else { '#1b73c1' }
    symbols <- if(length(unique(RFImp_score$Selected)) > 1) {  c('x', 'circle') } else { 'circle' }    

    p <- plot_ly(data = RFImp_score,
                 source = 'RFAcc_FP1',
                 height = plotheight,
                 width = 450)  %>%
      add_trace(x = RFImp_score$MeanDecreaseAccuracy,
                y = RFImp_score$Variables,
                type = 'scatter',
                mode = 'markers',
                color = factor(RFImp_score$Selected),
                colors = colors,
                symbol = factor(RFImp_score$Selected),
                symbols = symbols,
                marker = list(size  = 6),
                hoverinfo = "text",
                text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
                               '<br>',  'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
                               sep = '')) %>%
      layout(
        margin = list(l = 160, r= 20, b = 70, t = 50),
        hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
        xaxis =  list(title = 'Mean decrease accuracy index (%)',
                      tickformat = "%",
                      showgrid = F,
                      showline = T,
                      zeroline = F,
                      nticks = 5,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        yaxis =  list(categoryarray = RFImp_score$Variables,
                      autorange = T,
                      showgrid = F,
                      showline = T,
                      autotick = T,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        dragmode =  "select"
      ) %>%  add_annotations(x = 0.5,
                             y = 1.05,
                             textangle = 0,
                             font = list(size = 14,
                                         color = 'black'),
                             text = "Contribution to accuracy",
                             showarrow = F,
                             xref='paper',
                             yref='paper')

    p <- p %>% config(displayModeBar = F)
    p
  })


}
shinyApp(ui, server)

请检查以下内容:

library(shiny)
library(plotly)
library(data.table)

testDF <- data.table(MeanDecreaseAccuracy =  runif(10, min = 0, max = 1), Variables = letters[1:10], Selected = TRUE)
setorder(testDF, MeanDecreaseAccuracy)

ui <- fluidPage(
  plotlyOutput('RFAcc_FP1',  width = 450)
)

server <- function(input, output, session) {

  RFImp_score <- reactive({
    eventData <- event_data("plotly_selected", source = 'RFAcc_FP1_source', session)
    parsToChange <- eventData$y
    testDF[Variables %in% parsToChange, Selected := !Selected]
    testDF
  })

  output$RFAcc_FP1 <- renderPlotly({
    req(RFImp_score())
    plotheight <- length(RFImp_score()$Variables) * 80

    colors <- if (length(unique(RFImp_score()$Selected)) > 1) {
      c('#F0F0F0', '#1b73c1')
    } else {
      if (unique(RFImp_score()$Selected)) {
        '#1b73c1'
      } else {
        '#F0F0F0'
      }
    }

    symbols <-
      if (length(unique(RFImp_score()$Selected)) > 1) {
        c('x', 'circle')
      } else {
        if (unique(RFImp_score()$Selected)) {
          'circle'
        } else {
          'x'
        }
      }

    p <- plot_ly(data = RFImp_score(),
                 source = 'RFAcc_FP1_source',
                 height = plotheight,
                 width = 450) %>%
      add_trace(x = ~MeanDecreaseAccuracy,
                y = ~Variables,
                type = 'scatter',
                mode = 'markers',
                color = ~factor(Selected),
                colors = colors,
                symbol = ~factor(Selected),
                symbols = symbols,
                marker = list(size  = 6),
                hoverinfo = "text",
                text = ~paste('<br>', 'Parameter: ', ~Variables,
                              '<br>',  'Mean decrease accuracy: ', format(round(MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
                              sep = '')) %>%
      layout(
        margin = list(l = 160, r= 20, b = 70, t = 50),
        hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
        xaxis =  list(title = 'Mean decrease accuracy index (%)',
                      tickformat = "%",
                      showgrid = F,
                      showline = T,
                      zeroline = F,
                      nticks = 5,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        yaxis =  list(categoryarray = ~Variables,
                      autorange = T,
                      showgrid = F,
                      showline = T,
                      autotick = T,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        dragmode =  "select"
      ) %>%  add_annotations(x = 0.5,
                             y = 1.05,
                             textangle = 0,
                             font = list(size = 14,
                                         color = 'black'),
                             text = "Contribution to accuracy",
                             showarrow = F,
                             xref='paper',
                             yref='paper')

    p <- p %>% config(displayModeBar = F)
    p
  })


}
shinyApp(ui, server)

结果:

通常反应式方法可能更好,但由于我的

我选择坚持观察
 lapply(plotlist, function(THEPLOT) {
values[[paste('RFImp', THEPLOT, sep = '')]]   #..... etc
#......
})

最后我设法通过反转跟踪顺序解决了问题以实现所需的行为。 通过使 selected == T curveNumber 0selected == F curveNumber 1,每次进行相同的选择并反转时,event_data

之间切换
  curveNumber pointNumber         x y
1           0           0 0.3389429 g
2           0           1 0.3872325 j

  curveNumber pointNumber         x y
1           1           0 0.3389429 g
2           1           1 0.3872325 j

这是通过颜色和符号语句前面的!来实现的:

                mode = 'markers',
                color = ~factor(!Selected), 
                colors = colors,
                symbol = ~factor(!Selected), 

if(!is.null( values$RFImp_FP1)) { ...} 语句导致 observe({...}) 触发两次,但这没有进一步的影响,因为 values$Selected 仅在第一次发生变化。如果没有此声明,如果绘图不在您打开的第一页上(即在另一个选项卡或下拉按钮上),新的 Plotly 版本会导致应用程序抛出以下错误

Warning: The 'plotly_selected' event tied a source ID of 'RFAcc_FP1' is not registered. In order to obtain this event data, please add event_register(p, 'plotly_selected') to the plot (p) that you wish to obtain event data from.

正在运行的应用程序:

library(shiny)
library(plotly)
library(dplyr)
library(data.table)

testDF <- data.table( MeanDecreaseAccuracy =  runif(10, min = 0, max = 1), Variables = letters[1:10])
testDF$Selected <- T

ui <- fluidPage(
  plotlyOutput('RFAcc_FP1',  width = 450)
)

server <- function(input, output, session) {

  values <- reactiveValues(RFImp_FP1 = testDF)

  observe({

      values$Selected <- event_data("plotly_selected", source = 'RFAcc_FP1')

  })


  observeEvent(values$Selected, {
    parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
    if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
      data_df <- values$RFImp_FP1
      data_df[Variables %in% parsToChange, Selected := !Selected]
      values$RFImp_FP1 <- NULL
      values$RFImp_FP1 <- data_df
    }

  })


  output$RFAcc_FP1 <- renderPlotly({

    RFImp_score <- values$RFImp_FP1[order(MeanDecreaseAccuracy)]
    plotheight <- length(RFImp_score$Variables) * 80
    colors <- if(length(unique(RFImp_score$Selected)) > 1) { c( '#1b73c1', '#F0F0F0') } else { '#1b73c1' }
    symbols <- if(length(unique(RFImp_score$Selected)) > 1) {  c( 'circle', 'x') } else { 'circle' }    

    p <- plot_ly(data = RFImp_score,
                 source = 'RFAcc_FP1',
                 height = plotheight,
                 width = 450)  %>%
      add_trace(x = RFImp_score$MeanDecreaseAccuracy,
                y = RFImp_score$Variables,
                type = 'scatter',
                mode = 'markers',
                color = ~factor(!Selected), 
                colors = colors,
                symbol = ~factor(!Selected), 
                symbols = symbols,
                marker = list(size  = 6),
                hoverinfo = "text",
                text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
                               '<br>',  'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
                               sep = '')) %>%
      layout(
        margin = list(l = 160, r= 20, b = 70, t = 50),
        hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
        xaxis =  list(title = 'Mean decrease accuracy index (%)',
                      tickformat = "%",
                      showgrid = F,
                      showline = T,
                      zeroline = F,
                      nticks = 5,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        yaxis =  list(categoryarray = RFImp_score$Variables,
                      autorange = T,
                      showgrid = F,
                      showline = T,
                      autotick = T,
                      font = list(size = 8),
                      ticks = "outside",
                      ticklen = 5,
                      tickwidth = 2,
                      tickcolor = toRGB("black")
        ),
        dragmode =  "select"
      ) %>%  add_annotations(x = 0.5,
                             y = 1.05,
                             textangle = 0,
                             font = list(size = 14,
                                         color = 'black'),
                             text = "Contribution to accuracy",
                             showarrow = F,
                             xref='paper',
                             yref='paper')

    p <- p %>% config(displayModeBar = F)
    p
  })


}
shinyApp(ui, server)