防止 shiny 更新 plotly 的元素

Prevent shiny from updating elements of plotly

无论实际显示哪些点,我都试图保持绘图的颜色比例和大小比例不变。

ggplot 中,我可以使用 scale_color_gradient(limits=c(0,1)) 等参数设置这些常量。但是,我在 plot_ly 中找不到并行函数,并且由于其他原因,我无法在此处使用 ggplotly()

我相信 eventReactive() 也可以做到这一点,但我无法理解如何使用它。

这是一个最小的示例,其中绘图颜色和大小不断变化。

library(dplyr)
library(shiny)
library(plotly)

df <- as.data.frame(list("UserID"=c(1,1,1,1,2,2,2,2), 
                          "Category"=c('A','A','B','B','A','A','B','B'),
                          "Rate"=c(2,3,5,6,8,6,7,1),
                          "x"=c(1,3,5,7,2,4,6,8),
                          "y"=c(1,3,5,7,2,4,6,8)
                    ))

ui <- (fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("userInput","Select User", sort(unique(df$UserID)),
                  selected=1),
      checkboxGroupInput("CategoryInput", "Select Category", sort(unique(df$Category)),
                         selected=c('A','B'))
    ),

    mainPanel(
      plotlyOutput("mainPlot")#,
    )
  )
))

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

  # filter for both user and category
  filteredFull <- reactive({
      df %>% 
        filter(
          UserID == input$userInput,
          Category %in% input$CategoryInput
        )
  })

  output$mainPlot <- renderPlotly({
        plot_ly(data=filteredFull(), x=x, y=y,
                       color=Rate, size=Rate,
                       mode='markers')
  })
}

shinyApp(ui, server)

是否可以只更新显示的点,而不更新 color/size 的 scale/range?

Plotly 也有这些色标限制。它们嵌套在标记属性下。您可以设置色标的最大值和最小值(数值)以保持色标不变,而不管实际显示的点是什么。

我刚刚将 marker = list(cmin = 1, cmax = 8) 添加到 plot_ly 命令。因此,您必须扫描 df 以确定最大值和最小值。

代码如下:

library(dplyr)
library(shiny)
library(plotly)

df <- as.data.frame(list(
  "UserID" = c(1, 1, 1, 1, 2, 2, 2, 2), 
  "Category" = c('A', 'A', 'B', 'B', 'A', 'A', 'B', 'B'),
  "Rate" = c(2, 3, 5, 6, 8, 6, 7, 1),
  "x" = c(1, 3, 5, 7, 2, 4, 6, 8),
  "y" = c(1, 3, 5, 7, 2, 4, 6, 8)
))

ui <- (fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("userInput","Select User", sort(unique(df$UserID)), selected=1),
      checkboxGroupInput("CategoryInput", "Select Category", sort(unique(df$Category)), selected=c('A','B'))
    ),

    mainPanel(
      plotlyOutput("mainPlot"),
      plotlyOutput("mainPlotFixedSize")
    )
  )
))

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

  # filter for both user and category
  filteredFull <- reactive({
      df %>% 
        filter(
          UserID == input$userInput,
          Category %in% input$CategoryInput
        )
  })

  output$mainPlot <- renderPlotly({
    plot_ly(data=filteredFull(), x=x, y=y,
      color=Rate, size=Rate,
      mode='markers', marker = list(cmin = 1, cmax = 8))
  })

  output$mainPlotFixedSize <- renderPlotly({
    plot_ly(data=filteredFull(), x=x, y=y,
      color=Rate, mode='markers', 
      marker = list(sizemode = "area", size = Rate*3400, cmin = 1, cmax = 8))
  }) 
}

shinyApp(ui, server)