library(dplyr)
library(dbplyr)
library(DBI)
con <- dbConnect(
odbc::databricks(),
HTTPPath = "/sql/1.0/warehouses/300bd24ba12adf8e"
)
orders <- tbl(con, I("workshops.tpch.orders"))
customers <- tbl(con, I("workshops.tpch.customer"))
nation <- tbl(con, I("workshops.tpch.nation"))
prep_orders <- orders |>
left_join(customers, by = c("o_custkey" = "c_custkey")) |>
left_join(nation, by = c("c_nationkey" = "n_nationkey")) |>
mutate(
order_year = year(o_orderdate),
order_month = month(o_orderdate)
) |>
rename(customer = o_custkey) |>
select(-ends_with("comment"), -ends_with("key"))9 Dashboards
9.1 Preview app
Try out the finalized Shiny app
- Open the example-app.R file
Catch up
9.2 Data driven dropdown
- Load the
shinylibrary
library(shiny)- Run the following code to see the “stub” Shiny app
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = "FRANCE", selected = "FRANCE"),
plotOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderPlot({
# Your code here
})
},
options = list(height = 200)
)- Retrieve the country names from
nationinto a character vector. Save the values to a variable calledcountries
countries <- nation |>
pull(n_name)- Preview
countries
countries
#> [1] "ALGERIA" "ARGENTINA" "BRAZIL" "CANADA"
#> [5] "EGYPT" "ETHIOPIA" "FRANCE" "GERMANY"
#> [9] "INDIA" "INDONESIA" "IRAN" "IRAQ"
#> [13] "JAPAN" "JORDAN" "KENYA" "MOROCCO"
#> [17] "MOZAMBIQUE" "PERU" "CHINA" "ROMANIA"
#> [21] "SAUDI ARABIA" "VIETNAM" "RUSSIA" "UNITED KINGDOM"
#> [25] "UNITED STATES"- Replace the values of
choicesin the Shiny app. Now usecountriesas its source. Preview the app, the drop-down should now have the 25 countries as options
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
plotOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderPlot({
# Your code here
})
},
options = list(height = 200)
)9.3 Adding the plot
Port the code that creates the plot from the database
- Load the
ggplot2library
library(ggplot2)- Insert the full code that makes the country sales plot, the one in previous section. It should include the code that creates the local data, and the one that creates the plot itself. Place them in the area that says # Your code here. Make sure to replace,
country, withinput$country. Preview the app.
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
plotOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderPlot({
sales_by_year <- prep_orders |>
filter(n_name == input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
sales_by_year |>
ggplot() +
geom_col(aes(order_year, total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
})
},
options = list(height = 200)
)- Prefix
!!to theinput$countryentry where we create thesales_by_yearvariable. Preview the app.
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
plotOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderPlot({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
sales_by_year |>
ggplot() +
geom_col(aes(order_year, total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
})
},
options = list(height = 200)
)9.4 Interactive plots
Using ggiraph to add plot interactivity
- Load the
ggiraphlibrary
library(ggiraph)- In the Shiny app’s code, replace:
plotOUtput()withgirafeOutput()renderPlot()withrenderGirafe()geom_col()withgeom_col_interactive()
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
})
},
options = list(height = 200)
)- Load the
ggplotcode to a variable calledg, and then insertgirafe(ggobj = g)as the last code in the output’s code
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g)
})
},
options = list(height = 200)
)- In
geom_col_interactive()add the following arguments:data_id=order_yeartooltip=total_price
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g)
})
},
options = list(height = 200)
)9.5 Plot drill-down
Shows how to go a level deeper in to what has been clicked
- Add a
showModal()that reacts when a column in the plot is clicked:observeEvent(input$sales_plot_selected, {showModal(modalDialog())})
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g)
})
observeEvent(input$sales_plot_selected, {
showModal(modalDialog())
})
},
options = list(height = 200)
)- Add an
optionsargument to thegirafe()function call:options = list(opts_selection(type = "single")). Notice how only one column is highlighted at a time.
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g, options = list(opts_selection(type = "single")))
})
observeEvent(input$sales_plot_selected, {
showModal(modalDialog())
})
},
options = list(height = 200)
)- Add a
titleargument to themodalDialog()call. Use combination of thecountryandsales_plot_selectedvalues frominput
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g, options = list(opts_selection(type = "single")))
})
observeEvent(input$sales_plot_selected, {
showModal(
modalDialog(
title = paste0(input$country, " - ", input$sales_plot_selected)
)
)
})
},
options = list(height = 200)
)- Add a new
renderPLot()function, and name itoutput$montly_sales. Inside, add the full code from the Plot data by month section in the previous unit. Make sure to replacecountryandyear, withinput$country, andinput$sales_plot_selectedrespectively. Make sure to prefix!!when adding them to thefilter()call
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g, options = list(opts_selection(type = "single")))
})
output$monthly_sales <- renderPlot({
sales_by_month <- prep_orders |>
filter(
n_name == !!input$country,
order_year == !!input$sales_plot_selected
) |>
group_by(order_month) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_month$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
sales_by_month |>
ggplot() +
geom_col(aes(order_month, total_price)) +
scale_x_continuous(breaks = unique(sales_by_month$order_month)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(
title = "Sales by month",
subtitle = paste0(input$country, " - ", input$sales_plot_selected)
) +
theme_light()
})
observeEvent(input$sales_plot_selected, {
showModal(
modalDialog(
title = paste0(input$country, " - ", input$sales_plot_selected)
)
)
})
},
options = list(height = 200)
)- Finally, add
plotOutput("monthly_sales")to themodelDialog()call
shinyApp(
ui = fluidPage(
selectInput("country", "Country:", choices = countries, selected = "FRANCE"),
girafeOutput("sales_plot")
),
server = function(input, output) {
output$sales_plot <- renderGirafe({
sales_by_year <- prep_orders |>
filter(n_name == !!input$country) |>
group_by(order_year) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_year$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
g <- sales_by_year |>
ggplot() +
geom_col_interactive(aes(order_year, total_price, data_id = order_year, tooltip = total_price)) +
scale_x_continuous(breaks = unique(sales_by_year$order_year)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(title = "Sales by year", subtitle = input$country) +
theme_light()
girafe(ggobj = g, options = list(opts_selection(type = "single")))
})
output$monthly_sales <- renderPlot({
sales_by_month <- prep_orders |>
filter(
n_name == !!input$country,
order_year == !!input$sales_plot_selected
) |>
group_by(order_month) |>
summarise(
total_price = sum(o_totalprice, na.rm = TRUE)
) |>
collect()
breaks <- as.double(quantile(c(0, max(sales_by_month$total_price))))
breaks_labels <- paste(round(breaks / 1000000000, 1), "B")
sales_by_month |>
ggplot() +
geom_col(aes(order_month, total_price)) +
scale_x_continuous(breaks = unique(sales_by_month$order_month)) +
scale_y_continuous(breaks = breaks, labels = breaks_labels) +
xlab("Year") +
ylab("Total Sales") +
labs(
title = "Sales by month",
subtitle = paste0(input$country, " - ", input$sales_plot_selected)
) +
theme_light()
})
observeEvent(input$sales_plot_selected, {
showModal(
modalDialog(
title = paste0(input$country, " - ", input$sales_plot_selected),
plotOutput("monthly_sales")
)
)
})
},
options = list(height = 200)
)