导入文件并追加到R Shiny中以前加载的文件

时间:2019-05-25 05:17:20

标签: r shiny shinyapps

我正在尝试制作一个闪亮的应用程序,可以通过该应用程序顺序上传excel文件。每次我上传文件时,它都会添加到先前加载的文件中(假设它们具有相同的格式)。

我所做的是将df_all定义为一个空数据框。每次我单击“上传”并选择一个文件时,我都会执行bind_rows(df_all, df)。但这没有用。

有人可以帮我弄清楚我做错了什么吗?我花了几个小时尝试所有不同的东西,但没有成功。

# set working directory
setwd(my_working_directory)

ipak <- function(pkg){
    new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
    if (length(new.pkg)) 
        install.packages(new.pkg, dependencies = TRUE)
    sapply(pkg, require, character.only = TRUE)
}

packages <- c('devtools', 'readxl',
              'shiny', 'DT')
ipak(packages)

## ui
##---------------------------------------------------------------

ui <- fluidPage(
    fluidRow(
        column(9, h2('Import Excel'), align='center')    
    ),
    sidebarLayout(
        sidebarPanel(
            #----------------------Upload Files-----------------
            conditionalPanel(
                condition= " input.tabs == 'Upload_Files' ",

                fileInput('file', 'Choose Excel file',
                          accept = c(".xlsx")
                )
            )        
        ),        
        #------------------------------Main Panel------------------------    
        mainPanel(            
            tabsetPanel(
                id = 'tabs',               
                tabPanel('Upload_Files',
                         fluidRow (
                             column(12, DT::dataTableOutput('data.table1') ) 
                         ) 
                )
            )
        )
    )
)
##--------------------server-----------------------

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

    df_all = data.frame()

    output$data.table1 <- DT::renderDataTable({

        # input$file will be NULL initially.

        req(input$file)
        inFile <- input$file

        if(is.null(inFile)) {
            return(NULL)
        }

        df=read_excel(inFile$datapath)
        df_all = bind_rows(df_all, df)
        return(df_all)
    })
}
runApp(shinyApp(ui=ui, server=server))

1 个答案:

答案 0 :(得分:0)

您对df_all的更新存在缺陷,原因有两个:

  1. 当您在反应性块中引用df_all时,它将采用外部引用(在反应性块外部),然后将其分配给块内的df_all,而从不更新外部。在某些情况下,这建议使用<<-,尽管我不鼓励使用这种思维方式,因为它会导致程序设计出现问题(如果不必要,应该避免产生副作用)。还有...
  2. 您应该让外部df_all保持反应状态。

相反,尝试

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

    df_all <- reactiveVal(NULL)

    output$data.table1 <- DT::renderDataTable({
        req(input$file)
        olddf <- isolate(df_all())
        if(is.null(input$file)) return(NULL)
        df <- readr::read_excel(input$file$datapath)
        df <- dplyr::bind_rows(olddf, df)
        isolate(df_all(df))
        return(df)
    })
}

这应该在所有表的结构相似的情况下起作用。您可能希望通过一些预检查等方式(在一个名称中确认名称,在另一个中确认名称,等等)在行绑定时更加谨慎。

顺便说一句:我使用isolate(...),以便重新呈现表不会两次触发DT:renderDataTable。这并不是说渲染不能响应 else df_all所做的更改,但不能对自身施加(循环)反应。