2016-08-03 29 views
0

Ziel: Erstellen Sie eine glänzende App, die Daten vom Benutzer mit der Funktion fileInput() aufnehmen und dann die Daten löschen kann Hilfe von dplyr und vielen anderen Datenmanipulationstechniken und dann diese Daten plotten und eine Tabelle der gereinigten Daten anzeigen und haben auch einen Download-Button zum Herunterladen der bereinigten Daten.Reinigen eines Datenrahmens, der mit fileInput eingegeben und gezeichnet wurde - R Shiny

Was ich getan habe: Ich habe erfolgreich erstellt die App ohne die Dateieingabe. Ich habe einfach die Daten mit einem R-Skript bereinigt und dann das Skript vor dem Benutzerschnittstellenteil der App hinzugefügt und die App ausgeführt, und es hat gut funktioniert. Dies hatte jedoch keine Benutzereingabefähigkeit.

Der folgende Code ist eine vereinfachte Version meiner ui und Server-Seite der App, die versucht, Benutzereingabefunktionalität hinzuzufügen.

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) 

Die Eingangsdaten sieht wie folgt aus

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 

Vielen Dank für alle Hilfe.

Antwort

2

Ich habe die Daten verwendet, die Sie oben angegeben haben, und es ist mir gelungen, Ihren Code zu debuggen.

  • Zunächst einmal änderte ich den letzten Wert der Variablen dept-10 und in ähnlicher Weise die Entscheidungen in selectInput weil die Verschmelzung von a und Dept_Names hatte in einem leeren Datenrahmen geführt und die App abgestürzt war. Um einen Absturz zu verhindern, habe ich eine Funktion validate hinzugefügt, die erfordert, dass der Datensatz a nach dem Zusammenführen nicht leer ist.

  • Ich änderte C-c innerhalb selectInput

  • data hatte keinen Rückgabewert, und ich stellte es in die Liste, wo total_complete ein Datenrahmen zu reinigen ist und ofn ist der Name des Datenrahmens heruntergeladen

    return(list(total_complete = total_complete, ofn = ofn)) 
    
  • innerhalb von zwei render* Funktionen hinzugefügt I req(data()) die Fehler verhindert, wenn die data() nicht verfügbar ist (Wenn es NULL ist)

  • hinzugefügt data()$ innerhalb render* Funktionen total_complete und geändert Departments zu Dept

nicht leeren Grundstück und eine nicht leere Tabelle zu erhalten, nach dem Hochladen von Daten, die Sie in Ihrer Frage enthalten, setze den Wert von selectInput auf 10

Ich habe Kommentare im Code gemacht, um alle oben genannten Änderungen anzuzeigen.

Voll Code:

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) 
+1

Danke für die klare und präzise Antwort und für die Behebung von Problemen die ich hatte.Ich war in der Lage, Ihre Lösung zu nutzen und vor allem zu verstehen. Gut geschrieben und vermittelt. – glgeo1