From 34ca3be47a68292746edebbc0328710c437e2c38 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 16:21:11 +0200 Subject: [PATCH 01/11] First version of stacked barplot per status --- DESCRIPTION | 2 ++ NAMESPACE | 3 +++ R/plots.R | 31 +++++++++++++++++++++++++++++++ R/utils.R | 13 +++++++++++++ 4 files changed, 49 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index 157de409..88aa9c12 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -19,6 +19,8 @@ URL: https://mirai-solutions.ch, BugReports: https://github.com/miraisolutions/Covid19/issues Imports: config, + purrr, + stringr, golem, shiny, bsplus, diff --git a/NAMESPACE b/NAMESPACE index bbc3b780..597fc837 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -40,6 +40,7 @@ export(recovered_timeseries_csv_url) export(remove_legend) export(roundUp) export(run_app) +export(stackedbarplot_plot) export(time_evol_area_plot) export(time_evol_line_facet_plot) export(time_evol_line_plot) @@ -48,7 +49,9 @@ import(dplyr) import(ggplot2) import(leaflet) import(markdown) +import(purrr) import(shiny) +import(stringr) import(tidyr) importFrom(DT,DTOutput) importFrom(DT,datatable) diff --git a/R/plots.R b/R/plots.R index 7869901c..2f4d72f8 100644 --- a/R/plots.R +++ b/R/plots.R @@ -1,3 +1,34 @@ +#' stacked barplot status +#' +#' @param df data.frame +#' @param color string used to define color +#' @param percent logical to make the y axis in percent +#' @param y_min min value on y axis +#' +#' @import ggplot2 +#' +#' @return ggplot plot +#' @export +stackedbarplot_plot <- function(df, color, percent = T, text) { + if (percent) { + df$ratio.over.cases <- 100*df$ratio.over.cases + } + p <- df %>% + ggplot(aes(x = Country.Region, y = ratio.over.cases, fill = status, + text = paste0("percentage: ", round(ratio.over.cases, 1), "%
")))+ + basic_plot_theme() + + geom_col(position = position_stack(reverse = TRUE)) + + theme( + axis.text.x = element_text(angle = 30) + ) + if (percent) { + p <- p + scale_y_continuous(labels = function(x) paste0(x, "%")) #scale_y_continuous(labels = scales::label_percent(accuracy = 1))#scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + } + # p = p %>% + # fix_colors() + p +} + #' Time evolution as line plot #' #' @rdname time_evol_line_plot diff --git a/R/utils.R b/R/utils.R index 3c2183e0..1fce9c1f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -195,3 +195,16 @@ align_country_names_pop_reverse <- function(data){ ) data } +#' clean ggplotly legend +#' @param .plotly_x ggplotly object +#' @param .extract_str regular expression +#' @import stringr +clean_plotly_leg <- function(.plotly_x, .extract_str) { + # Inpects an x$data list in a plotly object, cleans up legend values where appropriate + if ("legendgroup" %in% names(.plotly_x)) { + # The list includes a legend group + .plotly_x$legendgroup <- stringr::str_extract(.plotly_x$legendgroup, .extract_str) + .plotly_x$name <- stringr::str_extract(.plotly_x$name, .extract_str) + } + .plotly_x +} From c1902cae21ff2d6b990eefaa66d01b0086c8eac3 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 17:30:57 +0200 Subject: [PATCH 02/11] update titles --- R/mod_stackedbarplot_status.R | 103 ++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 R/mod_stackedbarplot_status.R diff --git a/R/mod_stackedbarplot_status.R b/R/mod_stackedbarplot_status.R new file mode 100644 index 00000000..bf558826 --- /dev/null +++ b/R/mod_stackedbarplot_status.R @@ -0,0 +1,103 @@ +#' stackedbarplot_status UI Function +#' +#' @description A shiny Module. +#' +#' @param id,input,output,session Internal parameters for {shiny}. +#' +#' @noRd +#' +#' @importFrom shiny NS tagList +#' @importFrom shinycssloaders withSpinner +mod_stackedbarplot_ui <- function(id, n_highligth = 5){ + ns <- NS(id) + tagList( + fluidRow( + column(6, + uiOutput(ns("title_stackedbarplot_status")), + withSpinner(uiOutput(ns("plot_stackedbarplot_status"), height = 400)), + ) + ) + ) +} +#' stackedbarplot_status Server Function +#' +#' @param countries_data reactive data.frame for multiple countries +#' +#' @import dplyr +#' @import tidyr +#' @import ggplot2 +#' @import purrr +#' @noRd +mod_stackedbarplot_status_server <- function(input, output, session, df, n = 1000, w = 7, n_highligth = 5, istop = T){ + ns <- session$ns + # titles + if (istop) { + output$title_stackedbarplot_status <- renderUI(div(h4(paste0("Current top ", n_highligth, " status split")), align = "center", style = "margin-top:20px; margin-bottom:20px;")) + } else { + output$title_stackedbarplot_status <- renderUI(div(h4("Status split"), align = "center", style = "margin-top:20px; margin-bottom:20px;")) + } + + prep_data <- function(orig_data_aggregate, n, w){ + df1 <- orig_data_aggregate %>% + Covid19:::select_countries_n_cases_w_days(n = n, w = w) %>% + filter( date == max(date)) %>% + Covid19:::align_country_names_pop() %>% + mutate(country_name = Country.Region) %>% + Covid19:::get_pop_data() %>% + filter(population > 10^6) %>% # dropping countries with less than 1 M pop, needed? + Covid19:::align_country_names_pop_reverse() + df1 + } + df_pop <- reactive({prep_data(df(), n,w)}) + #df_pop = prep_data(df, n = 1000, w = 7) + + statuses <- c("deaths", "active", "recovered") + + pick_status <- function(df, stat){ + df <- df %>% + bind_cols(df[, stat] %>% setNames("Value")) + df + } + df_status = reactive({pick_status(df_pop(), "confirmed") %>% + arrange(desc(Value)) %>% + top_n(n_highligth, wt = Value) %>% + select(Country.Region,!!statuses)}) + + + # gather status and compute ratios + df_status_stack = reactive({df_status() %>% + gather("status", "countstatus", -Country.Region) %>% + group_by(Country.Region) %>% + mutate(n.pop = sum(countstatus), + ratio.over.cases = countstatus/n.pop) %>% + group_by(status) %>% + mutate(tot.status = sum(countstatus), + ratio.status = countstatus/tot.status) %>% + ungroup() %>% + mutate(Country.Region = as.factor(Country.Region), + status = factor(status, levels = statuses)) %>% + arrange(status)}) + + caption_explain <- "Status split per country." + + output$plot_stackedbarplot_status <- renderUI({ + tagList( + plotlyOutput(ns("plot_stackedbarplot_status_draw"), height = 400), + div(p(caption_explain), align = "center") + ) + }) + + output$plot_stackedbarplot_status_draw <- renderPlotly({ + p = df_status_stack() %>% + stackedbarplot_plot() %>% fix_colors() + p <- p %>% + ggplotly(tooltip = c("text", "fill")) %>% + layout(legend = list(orientation = "v", y = 1, yanchor = "left")) + + p$x$data <- + p$x$data %>% + purrr::map(clean_plotly_leg, "[^\\(][^,]*") + + p + }) +} From 7c31eba1ab025a171f344b08dc38e9e8b009bdc1 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 17:31:40 +0200 Subject: [PATCH 03/11] Addition new functions for 83 --- man-roxygen/ex-mod_stackedbarplot_status.R | 27 ++++++++++++++++++++++ man/clean_plotly_leg.Rd | 16 +++++++++++++ man/stackedbarplot_plot.Rd | 23 ++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 man-roxygen/ex-mod_stackedbarplot_status.R create mode 100644 man/clean_plotly_leg.Rd create mode 100644 man/stackedbarplot_plot.Rd diff --git a/man-roxygen/ex-mod_stackedbarplot_status.R b/man-roxygen/ex-mod_stackedbarplot_status.R new file mode 100644 index 00000000..8c9a6b5c --- /dev/null +++ b/man-roxygen/ex-mod_stackedbarplot_status.R @@ -0,0 +1,27 @@ +if (interactive()) { + library(shiny) + library(Covid19) + library(dplyr) + library(tidyr) + library(ggplot2) + library(plotly) + + ui <- fluidPage( + tagList( + Covid19:::golem_add_external_resources(), + Covid19:::mod_stackedbarplot_ui("plot", 5) + ) + ) + server <- function(input, output, session) { + + orig_data_aggregate = reactive({get_timeseries_full_data() %>% + get_timeseries_by_contagion_day_data() %>% + aggregate_province_timeseries_data() %>% + arrange(Country.Region)}) + + callModule(Covid19:::mod_stackedbarplot_status_server, "plot", orig_data_aggregate) + + } + runApp(shinyApp(ui = ui, server = server), launch.browser = TRUE) +} + diff --git a/man/clean_plotly_leg.Rd b/man/clean_plotly_leg.Rd new file mode 100644 index 00000000..57f63bd7 --- /dev/null +++ b/man/clean_plotly_leg.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{clean_plotly_leg} +\alias{clean_plotly_leg} +\title{clean ggplotly legend} +\usage{ +clean_plotly_leg(.plotly_x, .extract_str) +} +\arguments{ +\item{.plotly_x}{ggplotly object} + +\item{.extract_str}{regular expression} +} +\description{ +clean ggplotly legend +} diff --git a/man/stackedbarplot_plot.Rd b/man/stackedbarplot_plot.Rd new file mode 100644 index 00000000..4a67bb7a --- /dev/null +++ b/man/stackedbarplot_plot.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plots.R +\name{stackedbarplot_plot} +\alias{stackedbarplot_plot} +\title{stacked barplot status} +\usage{ +stackedbarplot_plot(df, color, percent = T, text) +} +\arguments{ +\item{df}{data.frame} + +\item{color}{string used to define color} + +\item{percent}{logical to make the y axis in percent} + +\item{y_min}{min value on y axis} +} +\value{ +ggplot plot +} +\description{ +stacked barplot status +} From f3cc1fd660ef83a848bfc5def27e6daac0eaa2ad Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 17:31:59 +0200 Subject: [PATCH 04/11] Added stacked barplot in page --- R/mod_global.R | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/R/mod_global.R b/R/mod_global.R index a3f347aa..7b588197 100644 --- a/R/mod_global.R +++ b/R/mod_global.R @@ -38,6 +38,11 @@ mod_global_ui <- function(id){ ) ), hr(), + fluidRow( + column(12, + mod_stackedbarplot_ui(ns("plot_stackedbarplot_status")) + ) + ), mod_add_table_ui(ns("add_table_world")) ) } @@ -138,6 +143,9 @@ mod_global_server <- function(input, output, session, orig_data, orig_data_aggre # > growth_death_rate callModule(mod_growth_death_rate_server, "plot_growth_death_rate", orig_data_aggregate) + # > stacked barplot with status split + callModule(mod_stackedbarplot_status_server, "plot_stackedbarplot_status", orig_data_aggregate) + # tables ---- callModule(mod_add_table_server, "add_table_world", world) From e2806dea4d4079c9d1f011cba84cd9fd4a0a5b4b Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 17:53:16 +0200 Subject: [PATCH 05/11] corrected title --- R/mod_stackedbarplot_status.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/mod_stackedbarplot_status.R b/R/mod_stackedbarplot_status.R index bf558826..077498ec 100644 --- a/R/mod_stackedbarplot_status.R +++ b/R/mod_stackedbarplot_status.R @@ -34,7 +34,7 @@ mod_stackedbarplot_status_server <- function(input, output, session, df, n = 100 if (istop) { output$title_stackedbarplot_status <- renderUI(div(h4(paste0("Current top ", n_highligth, " status split")), align = "center", style = "margin-top:20px; margin-bottom:20px;")) } else { - output$title_stackedbarplot_status <- renderUI(div(h4("Status split"), align = "center", style = "margin-top:20px; margin-bottom:20px;")) + output$title_stackedbarplot_status <- renderUI(div(h4("Status split by country"), align = "center", style = "margin-top:20px; margin-bottom:20px;")) } prep_data <- function(orig_data_aggregate, n, w){ From b10afc279feaa024f1d04ecd4f2606b8c9374d8b Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 17:53:38 +0200 Subject: [PATCH 06/11] Added stackedbarplot to comparison tab --- R/mod_country_comparison.R | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/R/mod_country_comparison.R b/R/mod_country_comparison.R index 2714b5f6..aa913c86 100644 --- a/R/mod_country_comparison.R +++ b/R/mod_country_comparison.R @@ -25,6 +25,11 @@ mod_country_comparison_ui <- function(id){ withSpinner(uiOutput(ns("lines_points_plots"))) ) ), + fluidRow( + column(12, + withSpinner(uiOutput(ns("status_stackedbarplot"))) + ) + ), mod_add_table_ui(ns("add_table_countries")) ) } @@ -106,6 +111,11 @@ mod_country_comparison_server <- function(input, output, session, orig_data_aggr callModule(mod_compare_nth_cases_plot_server, "lines_points_plots", countries_data, n = n, n_highligth = length(input$select_countries), istop = F) + output$status_stackedbarplot <- renderUI({ + mod_stackedbarplot_ui(ns("status_stackedbarplot")) + }) + callModule(mod_stackedbarplot_status_server, "status_stackedbarplot", countries_data, n = n, n_highligth = length(input$select_countries), istop = F) + # tables ---- callModule(mod_add_table_server, "add_table_countries", countries_data, maxrowsperpage = 10) }) From 571fb88d054e3d96db16280ba033ebb6c65664c0 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 18:04:32 +0200 Subject: [PATCH 07/11] GM: corercted stackedbarplot function and args --- R/plots.R | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/R/plots.R b/R/plots.R index 2f4d72f8..84539595 100644 --- a/R/plots.R +++ b/R/plots.R @@ -1,15 +1,13 @@ #' stacked barplot status #' #' @param df data.frame -#' @param color string used to define color #' @param percent logical to make the y axis in percent -#' @param y_min min value on y axis #' #' @import ggplot2 #' #' @return ggplot plot #' @export -stackedbarplot_plot <- function(df, color, percent = T, text) { +stackedbarplot_plot <- function(df, percent = T) { if (percent) { df$ratio.over.cases <- 100*df$ratio.over.cases } @@ -22,7 +20,7 @@ stackedbarplot_plot <- function(df, color, percent = T, text) { axis.text.x = element_text(angle = 30) ) if (percent) { - p <- p + scale_y_continuous(labels = function(x) paste0(x, "%")) #scale_y_continuous(labels = scales::label_percent(accuracy = 1))#scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + p <- p + scale_y_continuous(labels = function(x) paste0(x, "%")) } # p = p %>% # fix_colors() From 2de2d1a878ffbcb47cfdda25a5ae52aaa5635825 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 18:21:41 +0200 Subject: [PATCH 08/11] news updated --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 169e143c..eda27cc3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,8 @@ - fix trend order of area plot both global and country tabs, added utils funtion (#74) - correct plot titles for modules mod_compare_nth_cases_plot and mod_growth_death_rate (#66) - Add angle to bar-plot labels (#68) +- Add status split stackedbarplot (#83) + ### Covid19 1.1.6 (2020-04-06) From ddff96b1bf3d9a48c5210d8b8fb2b211145e1eeb Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Sun, 24 May 2020 23:48:19 +0200 Subject: [PATCH 09/11] roxygen --- R/mod_stackedbarplot_status.R | 1 + man/sort_type_hardcoded.Rd | 11 +++++++++++ man/stackedbarplot_plot.Rd | 6 +----- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 man/sort_type_hardcoded.Rd diff --git a/R/mod_stackedbarplot_status.R b/R/mod_stackedbarplot_status.R index 077498ec..34618295 100644 --- a/R/mod_stackedbarplot_status.R +++ b/R/mod_stackedbarplot_status.R @@ -27,6 +27,7 @@ mod_stackedbarplot_ui <- function(id, n_highligth = 5){ #' @import tidyr #' @import ggplot2 #' @import purrr +#' @importFrom plotly ggplotly layout #' @noRd mod_stackedbarplot_status_server <- function(input, output, session, df, n = 1000, w = 7, n_highligth = 5, istop = T){ ns <- session$ns diff --git a/man/sort_type_hardcoded.Rd b/man/sort_type_hardcoded.Rd new file mode 100644 index 00000000..d3a21e35 --- /dev/null +++ b/man/sort_type_hardcoded.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{sort_type_hardcoded} +\alias{sort_type_hardcoded} +\title{Sort type harcoded} +\usage{ +sort_type_hardcoded() +} +\description{ +Sort type harcoded +} diff --git a/man/stackedbarplot_plot.Rd b/man/stackedbarplot_plot.Rd index 4a67bb7a..09fbb9a1 100644 --- a/man/stackedbarplot_plot.Rd +++ b/man/stackedbarplot_plot.Rd @@ -4,16 +4,12 @@ \alias{stackedbarplot_plot} \title{stacked barplot status} \usage{ -stackedbarplot_plot(df, color, percent = T, text) +stackedbarplot_plot(df, percent = T) } \arguments{ \item{df}{data.frame} -\item{color}{string used to define color} - \item{percent}{logical to make the y axis in percent} - -\item{y_min}{min value on y axis} } \value{ ggplot plot From d18accb8c290d269b3b00043bf5bb3f01fb1c097 Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Mon, 25 May 2020 10:08:35 +0200 Subject: [PATCH 10/11] space missing before table --- R/mod_global.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/mod_global.R b/R/mod_global.R index 7b588197..0f71bb66 100644 --- a/R/mod_global.R +++ b/R/mod_global.R @@ -43,6 +43,7 @@ mod_global_ui <- function(id){ mod_stackedbarplot_ui(ns("plot_stackedbarplot_status")) ) ), + hr(), mod_add_table_ui(ns("add_table_world")) ) } From 955d9cdd65596b9b3bf37ea8ee312faefb6b06df Mon Sep 17 00:00:00 2001 From: Guido Maggio Date: Tue, 26 May 2020 21:42:09 +0200 Subject: [PATCH 11/11] Added additional label with count --- R/mod_stackedbarplot_status.R | 2 +- R/plots.R | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/R/mod_stackedbarplot_status.R b/R/mod_stackedbarplot_status.R index 34618295..35f78301 100644 --- a/R/mod_stackedbarplot_status.R +++ b/R/mod_stackedbarplot_status.R @@ -79,7 +79,7 @@ mod_stackedbarplot_status_server <- function(input, output, session, df, n = 100 status = factor(status, levels = statuses)) %>% arrange(status)}) - caption_explain <- "Status split per country." + caption_explain <- "Status split per country as of today." output$plot_stackedbarplot_status <- renderUI({ tagList( diff --git a/R/plots.R b/R/plots.R index 84539595..c15da820 100644 --- a/R/plots.R +++ b/R/plots.R @@ -8,12 +8,16 @@ #' @return ggplot plot #' @export stackedbarplot_plot <- function(df, percent = T) { + suffix = NULL if (percent) { df$ratio.over.cases <- 100*df$ratio.over.cases + suffix = "%" } p <- df %>% ggplot(aes(x = Country.Region, y = ratio.over.cases, fill = status, - text = paste0("percentage: ", round(ratio.over.cases, 1), "%
")))+ + text = paste0("percentage: ", round(ratio.over.cases, 1), suffix,"
", + label = paste("count: ", + formatC(countstatus, format = "f", big.mark = ",", digits = 0)))))+ basic_plot_theme() + geom_col(position = position_stack(reverse = TRUE)) + theme(