I'm trying to render two pie charts from one ggplot pie code by setting up a function to receive a different set of parameter values each time the plot function is called. This saves me having to write two sets of virtually identical code for each Pie.
The three parameters being passed are factor, title and scale. Pie1 has factor=age_group
, title="Age_Group Segmentation"
and scale=c("#ffd700", "#bcbcbc", "#ffa500", "#254290", "#f0e68c", "#808000")
.
Pie2 has factor=Outcome
, title="Outcome Segmentation"
and scale=c(#ffd700", "#bcbcbc", "#ffa500", "#254290")
I know in principle that the way to do this is:
plot_func <- function(factor, title, scale) {ggplot(dfnew, aes("", share, fill = factor)) + geom_bar( +
labs(x = NULL, y = NULL, fill = NULL,title = title) + scale_fill_manual(values = scale)))}
then call this plot_function in renderplot:
plot_func(group, title, scale)
with the parameter values.
The problem is I don't know the required syntax especially since a reactive data object is being passed into ggplot as well, data_mod(). I haven't found anything in stackoverflow to mimic what I'm trying to do. The full code including a sample dataframe is included.
library(shiny)
library(ggplot2)
library(dplyr)
# use the below if you want to increase the file size being inputed to 9MB
# options(shiny.maxRequestSize = 9.1024^2)
ui <- shinyUI(navbarPage(
"Example",
tabPanel("Data",
sidebarLayout(
sidebarPanel("Nothing here at the moment"),
mainPanel(
"Select Dashboard Panel for results.Click on
Select/All to make the plots render"
)
)),
tabPanel("Dashboard",
sidebarLayout(
sidebarPanel(
checkboxInput('all', 'Select All/None', value = TRUE),
uiOutput("year_month"),
tags$head(
tags$style(
"#year_month{color:red; font-
size:12px; font-style:italic;
overflow-y:scroll; max-height: 100px; background:
ghostwhite;}"
)
)
),
mainPanel(uiOutput("tb"))
))
))
complaint_id <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
age_group <- c(
"09 Months",
"03 Months",
"06 Months",
"Over A Year",
"12 Months",
"01 Months",
"09 Months",
"03 Months",
"06 Months",
"Over A Year",
"12 Months",
"01 Months"
)
closed_date_ym <- c(
"2019-09",
"2019-09",
"2019-09",
"2019-09",
"2019-09",
"2019-09",
"2019-08",
"2019-08",
"2019-08",
"2018-08",
"2019-08",
"2019-08"
)
officer <- c("A", "B", "C", "D", "A", "B", "C", "D", "A", "B", "C",
"D")
Outcome <- c(
"Excellent",
"Good",
"OK",
"Poor",
"Excellent",
"Good",
"OK",
"Poor",
"Excellent",
"Good",
"OK",
"Poor"
)
sample_data <- data.frame(complaint_id, age_group, closed_date_ym,
officer, Outcome)
server <- shinyServer(function(session, input, output) {
# Make it reactive
data <- reactive({
sample_data
})
# Have to modify the reactive data object to add a column of 1s(Ones) inorder
# that the Pie chart %s are calculated correctly within the segments. We apply
# this modification to a new reactive object, data_mod()
data_mod <- reactive({
req(data())
df <- data() %>% select(complaint_id, age_group, closed_date_ym,
officer, Outcome)
df$Ones <- rep(1, nrow(data()))
df
})
# creates a selectInput widget with unique YYYY-MM variables ordered from most
# recent to oldest time period
output$year_month <- renderUI({
req(data_mod())
data_ordered <- order(data_mod()$closed_date_ym, decreasing = T)
data_ordered <- data_mod()[data_ordered,]
checkboxGroupInput("variable_month",
"Select Month",
choices = unique(data_ordered$closed_date_ym))
})
observe({
req(data_mod())
data_ordered <- order(data_mod()$closed_date_ym, decreasing = T)
data_ordered <- data_mod()[data_ordered,]
updateCheckboxGroupInput(
session,
"variable_month",
choices = unique(data_ordered$closed_date_ym),
selected = if (input$all)
unique(data_ordered$closed_date_ym)
)
})
# This subsets the dataset based on what "variable month" above is selected
# and renders it into a Table
output$table <- renderTable({
req(data_mod())
dftable <- data_mod()
df_subset <- dftable[, 1:5][dftable$closed_date_ym %in%
input$variable_month, ]
},
options = list(scrollX = TRUE))
# This takes the modified reactive data object data_mod(), assigns it to a
# dataframe df. The dataset in df is subsetted based on the selected variable
# month above and assigned into a new data frame, dfnew. The Pie chart is
# built on the variables within dfnew.
plot_func <- function(factor, title, scale) {
group_by(factor) %>%
summarize(volume = sum(Ones)) %>%
mutate(share = volume / sum(volume) * 100.0) %>%
arrange(desc(volume))
ggplot(dfnew, aes("", share, fill = factor)) +
geom_bar(
width = 1,
size = 1,
color = "white",
stat = "identity"
) +
coord_polar("y") +
geom_text(aes(label = paste0(round(share, digits = 2), "%")),
position = position_stack(vjust = 0.5)) +
labs(
x = NULL,
y = NULL,
fill = NULL,
title = title
) +
guides(fill = guide_legend(reverse = TRUE)) +
scale_fill_manual(values = scale) +
theme_classic() +
theme(
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "#666666")
)
}
output$plot1 <- renderPlot({
req(data_mod(), input$variable_month)
df <- data_mod()
dfnew <- df[, 1:6][df$closed_date_ym %in% input$variable_month, ] %>%
plot_func(
factor = age_group,
title = "Age Group Segmentation",
scale = c(
"#ffd700",
"#bcbcbc",
"#ffa500",
"#254290",
"#f0e68c",
"#808000"
)
)
})
output$plot2 <- renderPlot({
req(data_mod(), input$variable_month)
df <- data_mod()
dfnew <- df[, 1:6][df$closed_date_ym %in% input$variable_month, ] %>%
plot_func(
factor = Outcome,
title = "Outcome Segmentation",
scale =
c("#ffd700", "#bcbcbc", "#ffa500", "#254290")
)
})
# the following renderUI is used to dynamically gnerate the tabsets when the file is loaded
output$tb <- renderUI({
req(data())
tabsetPanel(tabPanel("Plot",
plotOutput("plot1"), plotOutput("plot2")),
tabPanel("Data", tableOutput("table")))
})
})
shinyApp(ui = ui, server = server)
The expected results are to have two pie charts being rendered but I get the error message
Warning: Error in plot_func: unused argument (.)
Can someone help me out with this? Much appreciated.