繁体   English   中英

R Shiny:如何使用上传的 data.frame 扩展包含 data.frames 列表的反应?

[英]R Shiny: How to expand a reactive containing a list of data.frames with an uploaded data.frame?

我为此苦苦挣扎了几个小时:

在我的应用程序中,启动应用程序时会加载一个简单的测试数据集df 然后,用户可以通过文件上传添加更多数据集,然后从下拉菜单(此处为selectInput )选择他喜欢继续使用的数据集。

我没有做的事情:

启动应用程序后,反应式df_list应该只包含初始数据集df并且下拉菜单应该只包含值c("", "df") 通过上传(或其他方式)添加数据集后,应展开df_list (以及相应的下拉菜单)。 这样我就有了一个列表,其中包含用户可以从 select 中获取的所有可用数据集。

但我只设法创建了两个场景:下拉菜单包含df但添加数据集后我无法展开df_list 或者在我添加数据集之前下拉菜单保持空白,因此用户必须先添加数据集才能使用测试数据集。

我的代码示例:我通过创建 data.frame df_upload的 actionButton 来“模拟”文件上传。 以下示例不尝试使用附加数据集df_upload df_list

library(shiny)

# df available from start
df <- data.frame(Var = 1:10)

ui <- fluidPage(
  selectInput("select", label = "Select data", choices = c("")),
  actionButton("upload", "Simulate Upload"),
  tableOutput("tabdata")
)

server <- function(input, output, session) {
  
  # reactive that lists all datasets
  df_list <- reactive({list(df = df)})
  
  # 'upload' of second df
  df_upload <- eventReactive(input$upload, {
    data.frame(Var = 11:20)
  })
  
  # observes if df_list() gets expanded to update choices
  observeEvent(df_list(), {
    updateSelectInput(session = session,
                      inputId = "select",
                      choices = c("", names(df_list())))
  })
  
  # output of selected dataset
  output$tabdata <- renderTable({
    req(df_list())
    df_list()[[input$select]]
  }) 

}

shinyApp(ui, server)

这是我尝试过的许多事情之一(这成功添加了df_upload ,但在启动应用程序后最初无法在下拉菜单中显示df ):

library(shiny)

# df available from start
df <- data.frame(Var = 1:10)

ui <- fluidPage(
  selectInput("select", label = "Select data", choices = c("")),
  actionButton("upload", "Simulate Upload"),
  tableOutput("tabdata")
)

server <- function(input, output, session) {
  
  # reactive that lists all datasets
  df_list <- reactive({
    df_list <- list(df = df)
    
    # check if there is an uploaded df, and if yes add it to df_list
    # does not work, because it does not give me df_list only containing df 
    # in case no dataset was added yet.
    # is.null is not the proper way, because if df_upload does not exist yet,
    # it does not yield NULL. I also tried it unsuccessfully 
    # with exists("df_upload()")
    if (!is.null(df_upload())) {
      df_list[[2]] <- df_upload()
      names(df_list)[2] <- "df_upload"
    }
    return(df_list)
  })
  
  # 'upload' of second df
  df_upload <- eventReactive(input$upload, {
    data.frame(Var = 11:20)
  })

  # observes if df_list() gets expanded to update choices
  observeEvent(df_list(), {
    updateSelectInput(session = session,
                      inputId = "select",
                      choices = c("", names(df_list())))
  })
  
  # output of selected dataset
  output$tabdata <- renderTable({
    req(df_list())
    df_list()[[input$select]]
  })
  
}

shinyApp(ui, server)

基于@Limey 的评论使用 reactiveValues 的简单解决方案:

library(shiny)

# df available from start
df <- data.frame(Var = 1:10)

reactlog::reactlog_enable()

ui <- fluidPage(
  selectInput("select", label = "Select data", choices = c("df")),
  actionButton("upload", "Simulate Upload"),
  tableOutput("tabdata")
)

server <- function(input, output, session) {
  
  # empty reactiveValues rv to store all datasets in
  rv <- reactiveValues()
 
  # store the test df in rv
  rv$df <- df
  
  # 'upload' of second df and storing it in rv
   observeEvent(input$upload, {
     rv$df_upload <- data.frame(Var = 11:20)
  })
  
  # update selectInput choices 
  observe({
    updateSelectInput(session = session,
                      inputId = "select",
                      choices = names(rv),
                      selected = "df")
  })
  
  # output of selected dataset
  output$tabdata <- renderTable({
    rv[[input$select]]
  })

}

shinyApp(ui, server)

暂无
暂无

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

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