简体   繁体   English

带有条件 plotOut 的闪亮仪表板

[英]Shiny dashboard with conditional plotOut

I am just starting with shiny and dashboard, so any help is greatly appreciated!我刚开始使用闪亮的仪表板,因此非常感谢您的帮助!

I have a shinydashboard app displaying one row with two elements: A tabBox on the left with two tabPanel s, and a box on the right (to display a plot).我有一个 Shinydashboard 应用程序显示一行,其中包含两个元素:左侧的tabBox带有两个tabPanel s,右侧的一个box (用于显示绘图)。

What I want is to display a particular plot in the box depending on the active tabPanel .我想要的是根据活动tabPanel在框中显示特定图。 The plot should be not clickable when the first tab is active, but clickable when the second tab is active.当第一个选项卡处于活动状态时,该图不应可单击,但在第二个选项卡处于活动状态时可单击

My problem is that I only know how to set up the clickable property in the ui through the plotOutput function using the option click = "plot_click" .我的问题是我只知道如何使用选项click = "plot_click"通过plotOutput函数在ui设置 clickable 属性。 But this sets both plots as clickable.但这将两个图都设置为可点击。 Of course, removing the option click = "plot_click" sets both plots as not-clickable.当然,删除选项click = "plot_click"将两个图都设置为不可点击。 How can I make the clickable property depend on the active tab?如何使可点击属性依赖于活动选项卡?

What I tried: Place an if statement inside box() such that, depending on the id of the tabPanel , it would activate the option click = "plot_click" for the correct plot.我尝试过的:box()放置一个if语句,这样,根据tabPanel的 ID,它会激活选项click = "plot_click"以获得正确的绘图。 I failed at this.我失败了。

Here's the code.这是代码。 You can play with either plot by (un)commenting the desired plot inside box() .您可以通过(取消)注释box()内的所需图来玩任一图。

library(shiny)
library(shinydashboard)
library(ggplot2)

ui <- dashboardPage(

  dashboardHeader(title = "Conditional plotOutput click", titleWidth = 450),

  dashboardSidebar(disable = TRUE), 

  dashboardBody(

    fluidRow(
      tabBox(title = "Choose tab", id = "choose.tab", height = 250, selected = "Automatic", 
             tabPanel(title = "Automatic", id = "auto", sliderInput("slider", "Nobs:", 1, 10, 5)), 
             tabPanel(title = "Manual", id = "man")
      ), 

      box(title = "Plot", solidHeader = TRUE, 
          # plotOutput("plot1", height = 250)                     # Try me!
          plotOutput("plot2", height = 250, click = "plot_click") # Or me!
      )
    )
  )
)

server <- function(input, output) {
  set.seed(123)

  react.vals <- reactiveValues( 
    df     = data.frame(x = numeric(), y = numeric()), 
    plot1  = ggplot(), 
    plot2  = ggplot()
  )

  # Plot 1 - Automatic scatterplot:
  observe({
    scatter.data     <- data.frame(x = runif(input$slider), y = runif(input$slider))
    react.vals$plot1 <- ggplot(scatter.data, aes(x, y)) + geom_point(color = "red", size = 4) + 
      scale_x_continuous("x", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) +
      scale_y_continuous("y", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) + 
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
  })
  observeEvent(react.vals$plot1, { 
    output$plot1 <- renderPlot({ react.vals$plot1 })
  })

  # Plot 2 - Manual scatterplot through clicking:
  observeEvent(input$plot_click, {
    new.point     <- data.frame(x = input$plot_click$x,
                                y = input$plot_click$y)
    react.vals$df <- rbind(react.vals$df, new.point)
  })
  observe({
    react.vals$plot2 <- ggplot(react.vals$df, aes(x = x, y = y)) + geom_point(color = "red", size = 4) + 
      scale_x_continuous("x", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) +
      scale_y_continuous("y", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) + 
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
  })
  observeEvent(react.vals$plot2, { 
    output$plot2 <- renderPlot({ react.vals$plot2 })
  })
}

shinyApp(ui, server)

Thanks in advance, jorge提前致谢,豪尔赫

You can use uiOutput to define the characteristics of plotOutput according to the active tabPanel .您可以使用uiOutput定义的特性plotOutput根据活动tabPanel Below is your example adapted with uiOutput :以下是您使用uiOutput改编的uiOutput

library(shiny)
library(shinydashboard)
library(ggplot2)

ui <- dashboardPage(

  dashboardHeader(title = "Conditional plotOutput click", titleWidth = 450),

  dashboardSidebar(disable = TRUE), 

  dashboardBody(

    fluidRow(
      tabBox(title = "Choose tab", id = "choose_tab", height = 250, selected = "Automatic", 
             tabPanel(title = "Automatic", id = "auto", sliderInput("slider", "Nobs:", 1, 10, 5)), 
             tabPanel(title = "Manual", id = "man")
      ), 

      box(title = "Plot", solidHeader = TRUE, 
          uiOutput("test")
      )
    )
  )
)

server <- function(input, output) {
  set.seed(123)

  react.vals <- reactiveValues( 
    df     = data.frame(x = numeric(), y = numeric()), 
    plot1  = ggplot(), 
    plot2  = ggplot()
  )

  observe({
    if (input$choose_tab == "Automatic") {
      output$test <- renderUI({
        plotOutput("plot1", height = 250)
      })
    }
    else if(input$choose_tab == "Manual") {
      output$test <- renderUI({
        plotOutput("plot2", height = 250, click = "plot_click")
      })
    }
  })

  # Plot 1 - Automatic scatterplot:
  observe({
    scatter.data     <- data.frame(x = runif(input$slider), y = runif(input$slider))
    react.vals$plot1 <- ggplot(scatter.data, aes(x, y)) + geom_point(color = "red", size = 4) + 
      scale_x_continuous("x", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) +
      scale_y_continuous("y", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) + 
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
  })
  observeEvent(react.vals$plot1, { 
    output$plot1 <- renderPlot({ react.vals$plot1 })
  })

  # Plot 2 - Manual scatterplot through clicking:
  observeEvent(input$plot_click, {
    new.point     <- data.frame(x = input$plot_click$x,
                                y = input$plot_click$y)
    react.vals$df <- rbind(react.vals$df, new.point)
  })
  observe({
    react.vals$plot2 <- ggplot(react.vals$df, aes(x = x, y = y)) + geom_point(color = "red", size = 4) + 
      scale_x_continuous("x", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) +
      scale_y_continuous("y", breaks = seq(0, 1, .2), limits = c(0, 1), expand = c(0,0)) + 
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
  })
  observeEvent(react.vals$plot2, { 
    output$plot2 <- renderPlot({ react.vals$plot2 })
  })
}

shinyApp(ui, server)

Edit: Fixed a small typo in the R code.编辑:修复了 R 代码中的一个小错字。

Thanks, bretauv , this solves it!谢谢, bretauv ,这解决了!

I still needed to add two final changes to the code to have exactly what I wanted:我仍然需要对代码添加两个最终更改以完全满足我的要求:

  • Remove the plotOutput() inside box (not needed anymore).删除box的 plotOutput() (不再需要)。
  • Change plot2 to plot1 inside the first renderUI() call.更改plot2plot1第一内侧renderUI()调用。

Perhaps you want to edit your answer using these tips for future reference.也许您想使用这些提示编辑您的答案以供将来参考。

Thanks a lot!非常感谢! I've upvoted this answer.我已经赞成这个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM