目标:创建一个闪亮的应用程序,可以使用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
感谢您的帮助。
答案 0 :(得分:2)
我使用了您上面提供的数据,并设法调试您的代码。
首先,我将变量dept
的最后一个值更改为10,同样地将selectInput
中的选项更改为a
和Dept_Names
的合并导致数据框空白,应用程序崩溃了。为了防止崩溃,我添加了一个函数validate
,它要求合并后的数据集a
非空。
我在C
c
更改为selectInput
data
没有返回值,我将其设置为total_complete
是已清理数据框的列表,ofn
是下载数据框的名称:
return(list(total_complete = total_complete, ofn = ofn))
在我添加render*
的两个req(data())
函数中,如果data()
不可用(NULL
时
将data()$
个函数中的render*
添加到total_complete
并将Departments
更改为Dept
要获取非空图和非空表,在上传您问题中包含的数据后,请将selectInput
的值设置为10
我在代码中发表了评论,表明了上述所有变化。
完整代码:
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)