如何在rshiny中编辑上传的数据

时间:2017-11-30 08:51:25

标签: r shiny

以下是要求。

1)我需要浏览并上传一个excel文件(带有包readxl),用于获得一些我需要在闪亮窗口中显示为不同表输出的计算

2)手动编辑上传文件中的一些数据,它应自动反映在显示的结果中

3)我们应该能够下载编辑过的文件。

到目前为止我写过。我在输入数据中有列ID,曝光和频率。对于每个ID,我需要使用相应的曝光和频率来计算变量。我需要使用ID(这是唯一的)手动编辑频率和曝光。我添加了一个"更新"按钮。但改变不是永久性的。一旦我再次点击更新按钮,它就会返回

library(shiny)
ui = fluidPage( 

     titlePanel("HEllo world"),
     sidebarLayout(
          sidebarPanel(

               fileInput('file1', 'Choose xlsx file',
                         accept = c(".xlsx")),
               actionButton("go", "update"),
               numericInput('NewVal', 'Enter new Frequency',NULL),
               numericInput('NewExp', 'Enter new Exposure',NULL)),


          mainPanel(
               textInput('ID', 'Enter ID'),
               dataTableOutput('contents')

          )))

server = function(input,output){
     ef <- eventReactive(input$go, {
          infile <- input$file1 
          if(is.null(infile))
               return(NULL)
          file.rename(infile$datapath,paste(infile$datapath, ".xlsx", sep=""))
          data<-read_excel(paste(infile$datapath, ".xlsx", sep=""), 1)

          if(input$ID!="" && input$go>0){
               for( i in 1:nrow(data)){

                    if( input$ID == data$'ID'[i]){

                         if(!is.na(input$NewVal)){
                              data$' Frequency'[i] <- input$NewVal
                         }

                         if(!is.na(input$NewExp)){
                              data$'Exposure'[i] <- input$NewExp
                         }
                    }}}

          data
     }, ignoreNULL =  FALSE)  


     output$contents <- renderDataTable({ef()})}
shinyApp(ui,server)

更新!:根据一个答案,我对代码进行了一些更改。新代码似乎运行正常。以下是适用于可能需要相同问题帮助的人的工作代码。

ui = fluidPage( 

 titlePanel("HEllo world"),
  sidebarLayout(
  sidebarPanel(

  fileInput('file1', 'Choose xlsx file',
            accept = c(".xlsx")),
  actionButton("go", "update"),
  numericInput('NewVal', 'Enter new Frequency',NULL),
  numericInput('NewExp', 'Enter new Exposure',NULL)),


mainPanel(
  textInput('ID', 'Enter ID'),
  tableOutput('contents')

)))

  server = function(input,output){
  # Reactive value to save input data frame for use elsewhere
   original <- reactiveValues()

  observeEvent(input$file1, {
  theFile <- input$file1
   if(is.null(theFile)) {
    return(NULL)}
    **file.rename(theFile$datapath,paste(theFile$datapath, ".xlsx", sep=""))**
     original$oldData <- read_excel(paste(theFile$datapath, ".xlsx", sep = ""), 1)    
    })

   observeEvent(input$go, {

   original$newData <- original$oldData
   if(input$ID !="") {
    for( i in 1:nrow(original$oldData)){

     if( input$ID == original$oldData$'ID'[i]){

      if(!is.na(input$NewVal)){
        original$newData$'Frequency'[i] <- input$NewVal
      }

      if(!is.na(input$NewExp)){
        original$newData$'Exposure'[i] <- input$NewExp
      }
     }
    }
    **original$oldData<-original$newData**  }
  })

output$contents <- renderTable({
  if(!is.null(original$newData)) {
  original$newData}
else {
  original$oldData}
  })
  }
  shinyApp(ui = ui, server = server)

1 个答案:

答案 0 :(得分:0)

有些评论似乎在正确的轨道上发生了什么。可以使用几种解决方案,但我会分享对我来说最直观的方法。另外,我只会更改服务器功能。

server = function(input,output){
 # Reactive value to save input data frame for use elsewhere
 original <- reactiveValues()

 observeEvent(input$file1, {
   theFile <- input$file1
   if(is.null(theFile)) {return(NULL)}
   original$oldData <- read_excel(paste(theFile$datapath, ".xlsx", sep = ""), 1)    
 })

 observeEvent(input$goButton2, {
   original$newData <- original$oldData
   if(input$ID !="") {
          for( i in 1:nrow(data)){
                if( input$ID == dat$'ID'[i]){

                     if(!is.na(input$NewVal)){
                          original$newData$' Frequency'[i] <- input$NewVal
                     }

                     if(!is.na(input$NewExp)){
                          original$newData$'Exposure'[i] <- input$NewExp
                     }
                }
          }
   }
 })

 output$contents <- renderDataTable({
   if(!is.null(original$newData)) {original$newData}
   else {original$oldData}
 })
}

在单击go按钮之前,这不会更改表格输出。我没有完全测试它,因为我没有你的数据,但我相信这应该让你在最小的轨道上正确...我喜欢观察陈述,因为它们会引起副作用,看起来更开放比eventReactives或函数。

这仅对初始问题有帮助,即在输出中进行正确的更改并继续显示。如果这样可行,则添加下载功能应该相当容易,该功能会在文件更新时保存文件。

更新1

下面的代码应该按照您希望的方式执行。我添加了两种不同的功能来保存新数据框。注释掉的代码会在按下更新按钮时自动保存数据。没有注释的代码会创建一个用于下载数据的下载按钮。我还添加了一条基于频率和曝光计算新值的线。在数据集中将此列命名为Value。希望这可以帮助!

#### Example app for Exchange answer
library(shiny)
library(readxl)

ui = fluidPage( 

  titlePanel("HEllo world"),
  sidebarLayout(
    sidebarPanel(

      fileInput('file1', 'Choose xlsx file',
                accept = c(".xlsx")),
      actionButton("go", "update"),
      numericInput('NewVal', 'Enter new Frequency',NULL),
      numericInput('NewExp', 'Enter new Exposure',NULL),

      # Download button (goes with download handler below)
      # Use if desire is to save at press of button
      downloadButton("save", "Download")
    ),

    mainPanel(
      textInput('ID', 'Enter ID'),
      dataTableOutput('contents')
    )
  )
)

server = function(input,output){
  # Reactive value to save input data frame for use elsewhere
  original <- reactiveValues()

  observeEvent(input$file1, {
    theFile <- input$file1
    if(is.null(theFile)) {
      original$oldData <- NULL
    } else {
      original$oldData <- read_excel(theFile$datapath, 1)      
    }
  })

  observeEvent(input$go, {

    original$newData <- original$oldData
    if(input$ID !="") {
      for(i in 1:nrow(original$oldData)){

        if(input$ID == original$oldData$'ID'[i]){

          if(!is.na(input$NewVal)){
            original$newData$'Frequency'[i] <- input$NewVal
          }

          if(!is.na(input$NewExp)){
            original$newData$'Exposure'[i] <- input$NewExp
          }
          ### Make sure a column in your data set is named Value for this
          # Calculate a new column
          original$newData$'Value'[i] <- (original$newData$'Exposure'[i]*
                                            original$newData$'Frequency'[i])
        }
      }

      original$oldData<-original$newData  
    }

    ### Use this to automatically save table when update is clicked
    # write.csv(original$newData, 
    #           file = #Desired Pathname, 
    #           row.names = FALSE)
  })

  output$contents <- renderDataTable({
     if(!is.null(original$newData)) {
      original$newData}
    else {
      original$oldData
    }
  })

  ### Use this code below if desired saving is through download button
  # Server code for download button
  output$save <- downloadHandler(
    filename = function() {
      paste0("newData - ", Sys.Date(), ".csv")
    },

    content = function(con) {
      if (!is.null(original$newData)) {
        dataSave <- original$newData
      } else {
        dataSave <- original$oldData
      }
      con <- ## Desired save location... could just use `getwd()` to
        # save to working directory
      write.csv(dataSave, con)
    }
  )

}


shinyApp(ui = ui, server = server)