首页 > 解决方案 > 如何在 Shiny 应用程序中将上传的文件转换为 DataFrame

问题描述

我正在关注 Shiny 网站上的文件上传控制教程。

在此处输入图像描述

此代码允许加载 CSV 文件,并自动从上传的文件中呈现表格:

在此处输入图像描述

问题是我无法将此表作为数据框访问以进行进一步处理。

标签: rdataframeshiny

解决方案


只需设置一个反应块即可为您提供数据:

library(shiny)
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File",
        accept = c(
          "text/csv",
          "text/comma-separated-values,text/plain",
          ".csv")
        ),
      tags$hr(),
      checkboxInput("header", "Header", TRUE)
    ),
    mainPanel(
      tableOutput("contents")
    )
  )
)

server <- function(input, output) {
  mydata <- reactive({
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, it will be a data frame with 'name',
    # 'size', 'type', and 'datapath' columns. The 'datapath'
    # column will contain the local filenames where the data can
    # be found.
    req(input$file1, input$header, file.exists(input$file1$datapath))
    read.csv(input$file1$datapath, header = input$header)
  })
  output$contents <- renderTable({
    req(mydata())
    mydata()
  })
}

shinyApp(ui, server)

现在在任何其他地方你需要用新的东西做点什么data.frame,只需使用mydata(). (我唯一的改变是将一些行移动到一个新的反应块中,缩短renderTable块,并使用req(...)而不是笨拙的is.null方法。)


一些附加说明:

  • 通常在shiny应用程序中,反应块做好一件事可能非常有用,例如“获取数据”、“绘制数据”、“调整/更改数据”。正是这样,我将原来的“读取文件然后渲染它”的单个块分解为“读取文件”(向一个或多个消费者提供数据)和“渲染它”两个块。
  • 这需要与反应性相平衡,这意味着依赖于其他块的块越多,我所说的应用程序组件“过度抖动”的可能性就越大。例如,如果块“B”依赖于“A”,而块“C”同时依赖于“A”和“B”,那么您可能会看到以下更新时间表:

    1. “A”更新(出于某种原因)
    2. 基于“A”的“C”更新
    3. “B”基于“A”更新
    4. 基于“B”的“C”更新(即,一次更改的两次更新;这会产生用户可见的双重更改,并且对于某些绘图可能包括加倍的有限时间延迟)。
  • 结合两个项目符号:将“读取和渲染”分解为“读取”和“渲染”似乎是合理的。如果您需要处理数据(删除/添加列、过滤行等),

    • 如果您从不需要原始/原始数据,那么这种突变可能应该在“读取”阶段完成;
    • 如果您想在更改数据的同时引用原始数据,那么您可能需要“读取”、“更新”和“渲染”阶段/代码块;
    • 即使您从不需要参考原始数据,如果任何突变依赖于用户定义的值(selectInput,numericInput等),那么您可能应该使用“读取”、“更新”、“渲染”阶段,以便您不要每次用户更改其他字段之一时都不必重新读取数据

推荐阅读