我有一个简单的shiny app
,仅绘制一个chart
。我的data frame (df)
包含范围不同的variables
,例如:Year, Month, Category, Brand
。
在绘制图表时,我想根据上面列出的所有变量对数据进行切片,因此我将它们设置为dynamic inputs
。我有一个有效的代码,但是,此应用需要一些改进:
对于Category
和Brand
之类的变量,我做了一个额外的变量All
,该变量将所有类别/品牌绘制在一起。该值All
已在应用程序中预先选择。 c("All", sort(unique(as.character(df$Brand))))
。
在此app
中,我有4个不同的input variables
:年,月,类别,品牌。当我尝试不同的输入组合时,大多数情况下,一个输入会重置另一个输入。 F.e.如果我选择Year:2018,Months:1-6,然后再次将Year更改为2015,则此更改会将Month和所有其他输入重置为默认值。有什么解决方案可以使其同时工作?
第二个问题是当我选择特定的类别/品牌时。尽管我选择了其他特定值,但值All
仍然保持选中状态。选择其他特定值时,是否可以取消选择All
?
此外,我还包含了可工作的代码,以使我对要解决的问题有更好的了解:
library(shiny)
library(shinydashboard)
library(plyr)
library(ggplot2)
# Header -----------------------------------------------------------
header <- dashboardHeader(title= "DashBoard")
# Sidebar --------------------------------------------------------------
sm <- sidebarMenu(
menuItem(
text="Chart",
tabName="chart",
icon=icon("eye")
)
)
sidebar <- dashboardSidebar(sm)
# Body --------------------------------------------------
body <- dashboardBody(
# Layout --------------------------------------------
tabItems(
tabItem(
tabName="chart",
fluidPage(
fluidRow(
title = "Inputs", status = "warning", width = 2, solidHeader = TRUE, collapsible = TRUE,
uiOutput("Year"),
uiOutput("Month.Range"),
uiOutput("Category"),
uiOutput("Brand"),
plotOutput("Chart")
)
)
)
)
)
# Setup Shiny app UI components -------------------------------------------
ui <- dashboardPage(header, sidebar, body)
# Setup Shiny app back-end components -------------------------------------
server <- function(input, output) {
# -----------------------------------------------------------------------------
#reproducable data generation
set.seed(1992)
n=100
Year <- sample(2015:2018, n, replace = TRUE)
Month <- sample(1:12, n, replace = TRUE)
Category <- sample(c("Car", "Bus", "Bike"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:14, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100
df <- data.frame(Year, Month, Category, Brand, USD)
#----------------------------------------------------------------------------
#Generate input filters
#Year filter
output$Year <- renderUI({
selectInput("Year",
"Year:",
c(unique(as.character(df$Year))), selected = max(unique(as.character(df$Year))))
})
#Month filter
output$Month.Range <- renderUI({
df <- df[df$Year %in% input$Year,]
sliderInput("Month.Range", "Months:",
min = 1, max = max(unique(df$Month)), value = c(1, max(unique(df$Month))), step = 1)
})
#Category filter
output$Category<- renderUI({
df <- df[df$Year %in% input$Year,]
df <- df[df$Month >= input$Month.Range[1] & df$Month <= input$Month.Range[2],]
selectizeInput("Category",
"Category:",
choices = c("All", sort(unique(as.character(df$Category)))), multiple = T, selected = "All")
})
#Brand filtras
output$Brand <- renderUI({
df <- df[df$Year %in% input$Year,]
df <- df[df$Month >= input$Month.Range[1] & df$Month <= input$Month.Range[2],]
if(!"All" %in% input$Category){
df <- df[df$Category %in% input$Category,]
}
selectizeInput("Brand",
"Brand:",
choices = c("All", sort(unique(as.character(df$Brand)))), multiple = T, selected = "All")
})
#----------------------------------------------------------------------------
#Data manipulation and plotting
output$Chart <- renderPlot({
df <- df[df$Year %in% input$Year,]
#conditional to draw one or multiple categories
if(!"All" %in% input$Category){
df <- df[which(df$Category == input$Category),]
}
#conditional to draw one or multiple brands
if(!"All" %in% input$Brand){
df <- df[which(df$Brand %in% input$Brand),]
}
#aggredated data for plotting
df <- ddply(df, c("Year", "Month", "Brand"), summarise,
"USD" = sum(USD)/1000)
df = ddply(df, .(Month), transform, pos = cumsum(USD) - 0.5*USD)
#Chart
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity', width = .7, colour="black", lwd=0.1)+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE) +
ylab("Thousands of USD")+
geom_text(aes(label=ifelse(USD > 1, paste(round(USD,0),""),"")), colour="white", size = 6, fontface = "bold",
position=position_stack(vjust=0.5))
})
# -----------------------------------------------------------------------------
}
# Render Shiny app --------------------------------------------------------
shinyApp(ui, server)