【问题标题】:Cleaning a data frame inputed with fileInput and plotting it - R Shiny使用文件输入清理数据框输入并在 - R Shiny 中绘图
【发布时间】:2016-08-03 21:55:59
【问题描述】:

目标:创建一个闪亮的应用程序,该应用程序可以使用 fileInput() 函数从用户那里获取数据,然后在 dplyr 和许多其他工具的帮助下清理引入的数据数据操作技术,然后绘制此数据并显示已清理数据的表格,并且还有一个下载按钮来下载已清理数据。

我做了什么:我已经成功创建了没有 fileInput 的应用程序。我只是使用 R 脚本清理了数据,然后在应用程序的用户界面部分之前添加了脚本并运行了应用程序,它运行良好。但是,这没有用户输入功能。

下面的代码是我的应用程序的 ui 和服务器端的简化版本,它尝试添加用户输入功能。

Dept <- c(1,2,3)
DepartmentName <-c("abc","def","ghi")
Dept_Names <- cbind.data.frame(Dept,DepartmentName)

ui <- dashboardPage(   
  dashboardHeader(title="ABC"),
  dashboardSidebar(width = 150,
                   sidebarMenu(  
          menuItem("DataInput",tabName = "DataInput"),      
          menuItem("Dashboard", tabName = "Dashboard")
                   )),
  dashboardBody(
    tabItems(
      tabItem(tabName = "DataInput", 
              box(fileInput('file1', 'Choose CSV File',
                            accept=c('.csv')),
                  tags$hr(),
                  checkboxInput('header', 'Header', TRUE),
                  radioButtons('sep', 'Separator',
                               c(Comma=',',
                                 Semicolon=';',
                                 Tab='\t'),
                               ','),
                  actionButton("Load", "Load the File"))
      ),
      tabItem( tabName = "Dashboard",
               fluidRow(column(9,box(status = "primary",plotOutput("plot1"))
               ),
               column(3,
                      box(title="Controls",
                          selectInput(inputId = "Dept", 
                                      label = "Select", 
                                      choices = C(1,2,3)), 
                          numericInput(inputId = "ClassNum", 
                                       label = "Enter the Class Number", value = 1, min=0, max=100000),
                          status = "warning", solidHeader = TRUE, width="100%"),

                      downloadButton('downloadData', 'Download')

                )
              ), 
               box(DT::dataTableOutput("table"), width = "100%,",status = "primary")
      )
    )
  )
)

server <- function(input,output) { 

  data <- reactive({
    if(input$Load == 0){return()}
    inFile <- input$file1
    if (is.null(inFile)){return(NULL)}

    isolate({ 
      input$Load
      a <- read.csv(inFile$datapath, header = input$header,sep = input$sep,stringsAsFactors =FALSE)

      options(stringsAsFactors = FALSE) 
      a <- a[,1:5] 
      names(a) <- c("Dept","Description","Price","ClassNum","Quantity") 

      a <- a %>%
        filter(Quantity > 0) %>%
        filter(!(Price==""))  

      for (i in 1:length(a)) {  
        for (j in 1:nrow(a)) {
          if (i==2) {next}
          a[j,i] <- gsub(",", "", a[j,i])
        }  
      }  
      rm(i,j)  

      a <- merge(a,Dept_Names, by="Dept")

      for (j in 1:nrow(a)) { 
        if (a$ClassNum[j]=="") {a[j,4] <-0} else {a[j,4] <- a$ClassNum[j]}
      } 
      rm(j)

      a$Dept <- as.numeric(as.character(a$Dept))
      a$ClassNum <- as.numeric(as.character(a$ClassNum))
      a$Price <- as.numeric(as.character(a$Price))
      a$Quantity <- as.numeric(as.character(a$Quantity))

      a <- a %>%
        mutate(Revenue=Price*Quantity,Key1=paste(Dept, "_", ClassNum, sep="")) 

      total_complete <- a %>%
        group_by(Dept, ClassNum) %>%
        summarise(Revenue=sum(Revenue)) %>%
        arrange(Dept, desc(Revenue)) %>%
        mutate(Key1=paste(Dept, "_", ClassNum, sep="")) 

      ofn <- paste0("ABC",Sys.time(),".csv")
      ofn <- gsub(":","_",ofn)

    })

  })


  output$downloadData <- downloadHandler(
    filename = data()$ofn,
    content = function(file) {
      write.csv(data()$total_complete, file, row.names = FALSE)
    }
  )


  output$table <- DT::renderDataTable(DT::datatable({data1 <- data()$total_complete[data()$total_complete[,1]==input$Dept ,]
  }))

  output$plot1 <- renderPlot({

    ggplot(total_complete[total_complete$Department==input$Dept,], 
           aes(reorder(x=Key1,desc(Revenue)), y=Revenue, fill=Key1)) +
      geom_bar(stat="identity") +
      theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5)) 
  })



} 



shinyApp(ui, server)

输入数据如下所示

Dept #  Description Retail  Class # Q
10  MOP 11.99   100 1
10  Broom   7.99    101 2
10  soap    5.99    102 3
10  key 7.99    103 4
10  salmon  34.99   104 5
10  steak   11.99   105 5
10  wine    9.99    106 7

感谢所有帮助。

【问题讨论】:

    标签: r reactive-programming shiny shinydashboard


    【解决方案1】:

    我使用了您在上面提供的数据,并设法调试了您的代码。

      1234563应用程序崩溃了。为了防止崩溃,我添加了一个函数validate,它要求合并后的数据集a不为空。
    • 我在selectInput内将C更改为c

    • data 没有返回值,我将其设置为列表,其中total_complete 是已清理的数据框,ofn 是下载的数据框的名称:

      return(list(total_complete = total_complete, ofn = ofn))
      
    • 在两个render* 函数中,我添加了req(data()),如果data() 不可用(当它是NULL)时,它可以防止错误

    • render* 函数中添加了data()$total_complete 并将Departments 更改为Dept

    要获得非空图和非空表,请在上传问题中包含的数据后,将selectInput 的值设置为10

    我在代码中创建了 cmets 以指示上述所有更改。

    完整代码:

    library(shiny)
    library(shinydashboard)
    library(ggplot2)
    library(dplyr)
    
    rm(ui)
    rm(server)
    
    Dept <- c(1,2,10) # changed 3 to 10 to avoid an empty data set a after merging.
    DepartmentName <-c("abc","def","ghi")
    Dept_Names <- cbind.data.frame(Dept,DepartmentName)
    
    ui <- dashboardPage(   
      dashboardHeader(title="ABC"),
      dashboardSidebar(width = 150,
                       sidebarMenu(  
                         menuItem("DataInput",tabName = "DataInput"),      
                         menuItem("Dashboard", tabName = "Dashboard")
                       )),
      dashboardBody(
        tabItems(
          tabItem(tabName = "DataInput", 
                  box(fileInput('file1', 'Choose CSV File',
                                accept=c('.csv')),
                      tags$hr(),
                      checkboxInput('header', 'Header', TRUE),
                      radioButtons('sep', 'Separator',
                                   c(Comma=',',
                                     Semicolon=';',
                                     Tab='\t',
                                     Whitespace = " "),
                                   ','),
                      actionButton("Load", "Load the File"))
          ),
          tabItem( tabName = "Dashboard",
                   fluidRow(column(9,box(status = "primary", plotOutput("plot1"))
                   ),
                   column(3,
                          box(title="Controls",
                              selectInput(inputId = "Dept", 
                                          label = "Select", 
                                          choices = c(1,2,10)), # changed C to c and 3 to 10 
                              numericInput(inputId = "ClassNum", 
                                           label = "Enter the Class Number", value = 1, min=0, max=100000),
                              status = "warning", solidHeader = TRUE, width="100%"),
    
                          downloadButton('downloadData', 'Download')
    
                   )
                   ), 
                   box(DT::dataTableOutput("table"), width = "100%,",status = "primary")
          )
        )
      )
    )
    
    server <- function(input,output) { 
    
      data <- reactive({
        if(input$Load == 0) {
          return(NULL)
        }
        inFile <- input$file1
        if (is.null(inFile)) {
          return(NULL)
        }
          a <- read.csv(inFile$datapath, header = input$header,sep = input$sep,stringsAsFactors =FALSE)
    
          options(stringsAsFactors = FALSE) 
          a <- a[,1:5] 
          names(a) <- c("Dept","Description","Price","ClassNum","Quantity") 
    
          a <- a %>%
            filter(Quantity > 0) %>%
            filter(!(Price==""))  
    
          for (i in 1:length(a)) {  
            for (j in 1:nrow(a)) {
              if (i==2) {next}
              a[j,i] <- gsub(",", "", a[j,i])
            }  
          }  
          rm(i,j)  
    
          # You have to be careful here because it can be an empty data frame!
          a <- merge(a, Dept_Names, by="Dept")
    
          validate(
            need(nrow(a) != 0, 'Merge was not successful')
          )
    
    
          for (j in 1:nrow(a)) { 
            if (a$ClassNum[j]=="") {
              a[j,4] <-0
            } else {
              a[j,4] <- a$ClassNum[j]
            }
          } 
          rm(j)
    
          a$Dept <- as.numeric(as.character(a$Dept))
          a$ClassNum <- as.numeric(as.character(a$ClassNum))
          a$Price <- as.numeric(as.character(a$Price))
          a$Quantity <- as.numeric(as.character(a$Quantity))
    
          a <- a %>%
            mutate(Revenue=Price*Quantity,Key1=paste(Dept, "_", ClassNum, sep="")) 
    
          total_complete <- a %>%
            group_by(Dept, ClassNum) %>%
            summarise(Revenue=sum(Revenue)) %>%
            arrange(Dept, desc(Revenue)) %>%
            mutate(Key1=paste(Dept, "_", ClassNum, sep="")) 
    
          ofn <- paste0("ABC",Sys.time(),".csv")
          ofn <- gsub(":","_",ofn)
    
    
          # It looks like that you want to return a list
          # total_complete is a processed data frame and ofn is a name of the file
          # that is going to be downloaded
          return(list(total_complete = total_complete, ofn = ofn))
    
        })
    
    
      output$downloadData <- downloadHandler( 
        filename = function() { # added a function as in an example from ?downloadHandler
          data()$ofn
        },
        content = function(file) {
          write.csv(data()$total_complete, file, row.names = FALSE)
        }
      )
    
    
      output$table <- DT::renderDataTable({ 
        req(data()) # require that data() is available
        DT::datatable(data()$total_complete[data()$total_complete[,1]==input$Dept ,])
      })
    
      output$plot1 <- renderPlot({
        req(data()) # require that data() is available
    
        # there is no such variable as "Department" hence changed to $Dept
        # added data()$
        ggplot(data()$total_complete[data()$total_complete$Dept==input$Dept,], 
               aes(reorder(x=Key1,desc(Revenue)), y=Revenue, fill=Key1)) +
          geom_bar(stat="identity") +
          theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5)) 
      })
    } 
    
    shinyApp(ui, server)
    

    【讨论】:

    • 感谢简洁明了的回答以及解决我遇到的问题。我能够使用您的解决方案,更重要的是理解它。写得很好,传达得很好。
    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 2019-07-27
    • 2013-11-11
    • 2021-12-23
    • 2021-05-08
    • 2020-06-27
    • 2018-04-27
    • 2021-10-27
    相关资源
    最近更新 更多