【问题标题】:Getting the same plot for different subsets of data in shiny为闪亮的不同数据子集获取相同的图
【发布时间】:2021-06-08 10:54:13
【问题描述】:

我正在尝试创建一组动态图,这些图会根据数据中因子的数量而变化。问题是闪亮多次显示最后评估的图。 我尝试创建原始代码的简单版本以提供可重现的示例。 我根据滑块输入生成了许多正态分布,每个分布都由一个因子值(A、B 或 C)识别。根据选择的分布数量,我想单独绘制每个分布,但正如我所说,我得到循环中的最后一个分布重复多次。

    max_plots <- 3

ui <- fluidPage(
  
  headerPanel("Dynamic number of plots"),
  
  sidebarPanel(
    sliderInput("n", "Number of plots", value=1, min=1, max=3)
  ),
  
  mainPanel(
    # This is the dynamic UI for the plots
    uiOutput("plots")
  )
)

server <- function(input, output) {
  
  data_sim <- reactive({
    if(input$n == 1){
      y <- rnorm(n = 1000,mean = 0,sd = 1)
      x <- rep("A",1000)
      f <- "A"
    }else if(input$n == 2){
      y <- c(rnorm(n = 1000,mean = 10,sd = 2.5),
              rnorm(n = 1000,mean = -10,sd = 2.5))
      x <- c(rep("A",1000),rep("B",1000))
      f <- c("A","B")
    }else{
      y <- c(rnorm(n = 1000,mean = 20,sd = 2.5),
            rnorm(n = 1000,mean = 30,sd = 2.5),
            rnorm(n = 1000,mean = 40,sd = 2.5))
      x <- c(rep("A",1000),rep("B",1000),rep("C",1000))
      f <- c("A","B","C")
    }
    d <- list(data = data.frame(X=x,Y=y),fac = f)
    d
  })
  
  # Insert the right number of plot output objects into the web page
  output$plots <- renderUI({
    plot_output_list <- lapply(1:input$n, function(i) {
      plotname <- paste("plot", i, sep="")
      plotOutput(plotname, height = 280, width = 250)
    })
    
    # Convert the list to a tagList - this is necessary for the list of items
    # to display properly.
    do.call(tagList, plot_output_list)
  })
  
  # Call renderPlot for each one. Plots are only actually generated when they
  # are visible on the web page.
  for (i in 1:input$n) {
    # Need local so that each item gets its own number. Without it, the value
    # of i in the renderPlot() will be the same across all instances, because
    # of when the expression is evaluated.
    data <- data_sim()$data %>% filter(X == data_sim()$fac[i])
    local({
      my_i <- i
      plotname <- paste("plot", my_i, sep="")
      
      output[[plotname]] <- renderPlot({
        plot(density(data$Y))
      })
    })
  }
}

shinyApp(ui, server)

【问题讨论】:

  • 这可能是由于您使用了for 循环。如果您将其替换为 lapplypurrr::map,您可能会发现这样可行:请参阅我的回答 here 以了解类似问题
  • 感谢您的建议。讨论实际上帮助我找到了一个可行的解决方案。我只是将数据提取的部分移到 local() 块中,它可以工作。
  • 如果您找到了问题的答案,您可以通过包含以下答案自行回答您自己的问题。它可能会在未来对其他人有所帮助。

标签: r shiny shinydashboard


【解决方案1】:

我发现一个可行的解决方案是将数据提取部分放在本地块中。这是工作示例。

max_plots <- 3

ui <- fluidPage(
  
  headerPanel("Dynamic number of plots"),
  
  sidebarPanel(
    sliderInput("n", "Number of plots", value=1, min=1, max=3)
  ),
  
  mainPanel(
    # This is the dynamic UI for the plots
    uiOutput("plots")
  )
)

server <- function(input, output) {
  
  data_sim <- reactive({
    if(input$n == 1){
      y <- rnorm(n = 1000,mean = 0,sd = 1)
      x <- rep("A",1000)
      f <- "A"
    }else if(input$n == 2){
      y <- c(rnorm(n = 1000,mean = 10,sd = 2.5),
              rnorm(n = 1000,mean = -10,sd = 2.5))
      x <- c(rep("A",1000),rep("B",1000))
      f <- c("A","B")
    }else{
      y <- c(rnorm(n = 1000,mean = 20,sd = 2.5),
            rnorm(n = 1000,mean = 30,sd = 2.5),
            rnorm(n = 1000,mean = 40,sd = 2.5))
      x <- c(rep("A",1000),rep("B",1000),rep("C",1000))
      f <- c("A","B","C")
    }
    d <- list(data = data.frame(X=x,Y=y),fac = f)
    d
  })
  
  # Insert the right number of plot output objects into the web page
  output$plots <- renderUI({
    plot_output_list <- lapply(1:input$n, function(i) {
      plotname <- paste("plot", i, sep="")
      plotOutput(plotname, height = 280, width = 250)
    })
    
    # Convert the list to a tagList - this is necessary for the list of items
    # to display properly.
    do.call(tagList, plot_output_list)
  })
  
  # Call renderPlot for each one. Plots are only actually generated when they
  # are visible on the web page.
observeEvent(input$n,{
  for (i in 1:input$n) {
    # Need local so that each item gets its own number. Without it, the value
    # of i in the renderPlot() will be the same across all instances, because
    # of when the expression is evaluated.
    
    local({
      my_i <- i
      data <- data_sim()$data %>% filter(X == data_sim()$fac[my_i])
      plotname <- paste("plot", my_i, sep="")
      
      output[[plotname]] <- renderPlot({
        plot(density(data$Y))
      })
    })
  }
})
}

shinyApp(ui, server)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-03
    • 2023-04-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2016-12-09
    相关资源
    最近更新 更多