From 192ef98752d5fe2221d6e928613752546c4206f3 Mon Sep 17 00:00:00 2001 From: gnoblet Date: Wed, 21 Dec 2022 10:42:03 -0500 Subject: [PATCH] Remove dependency to ggblanket --- R/bar.R | 162 +++++++++++++++++++++++++++++++++--------------- R/point.R | 101 +++++++++++++++++------------- R/theme_reach.R | 145 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 296 insertions(+), 112 deletions(-) diff --git a/R/bar.R b/R/bar.R index 094b97a..24ddae8 100644 --- a/R/bar.R +++ b/R/bar.R @@ -4,69 +4,133 @@ #' @param x A numeric column. #' @param y A character column or coercible as a character column. #' @param group Some grouping categorical column, e.g. administrative areas or population groups. -#' @param palette Palette name from 'pal_reach()'. -#' @param percent TRUE or FALSE. Should the x-labels be displayed as percentages? Default to TRUE. -#' @param reverse Boolean indicating whether the palette should be reversed. -#' @param family The font family for all plot's texts. Default to "Leelawadee". -#' @param alpha Transparency. -#' @param width Width. +#' @param flip TRUE or FALSE. Default to TRUE or horizontal bar plot. +#' @param percent TRUE or FALSE. Should the x-labels (and text labels if present) be displayed as percentages? Default to TRUE. +#' @param position Should the chart be stacked? Default to "dodge". Can take "dodge" and "stack". +#' @param alpha Fill transparency. #' @param x_title The x scale title. Default to NULL. #' @param y_title The y scale title. Default to NULL. #' @param group_title The group legend title. Default to NULL. -#' @param position Should the chart be stacked? Default to "dodge". Can take "dodge" and "stack". #' @param title Plot title. Default to NULL. #' @param subtitle Plot subtitle. Default to NULL. -#' @param caption Caption title string. Default to NULL. -#' @param text_size The size of all text other than the title, subtitle and caption. Defaults to 10. -#' @param title_size The size of the title text. Defaults to 14. -#' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". -#' @param legend_rev Reverse the color in the guide? Default to TRUE. -#' @param ... Other arguments to be passed to "ggblanket::gg_col" -#' -#' @description `ggblanket` as internals for deciding whether the bar chart is horizontally readable. +#' @param caption Plot caption. Default to NULL. +#' @param add_text TRUE or FALSE. Add the value as text. +#' @param add_text_suffix If percent is FALSE, should we add a suffix to the text label? +#' @param theme Whatever theme. Default to theme_reach(). #' #' @return A bar chart #' #' @export -bar_reach <- function(df, x, y, group = NULL, percent = TRUE, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, width = 0.5, x_title = NULL, y_title = NULL, group_title = NULL, position = "dodge", title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", legend_rev = TRUE, ...){ +bar <- function(df, x, y, group = NULL, flip = TRUE, percent = TRUE, position = "dodge", alpha = 1, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, add_text = FALSE, add_text_suffix = "", theme = theme_reach()){ - pal <- pal_reach(palette) + # To do : + # - automate bar width and text size, or at least give the flexibility and still center text + # - add facet possibility - if(is.null(pal)) rlang::warn( - c(paste0("There is no palette '", palette, "' for initiative 'reach'. Fallback to ggblanket's default color palette."), - "i" = paste0("Use `pal_reach(show_palettes = T)` to see the list of availabale palettes.") + # Prepare group, x and y names + # if (is.null(x_title)) x_title <- rlang::as_name(rlang::enquo(x)) + # if (is.null(y_title)) y_title <- rlang::as_name(rlang::enquo(y)) + # if (is.null(group_title)) group_title <- rlang::as_name(rlang::enquo(group)) + + # Mapping + g <- ggplot2::ggplot( + df, + mapping = ggplot2::aes(x = {{ x }}, y = {{ y }}, fill = {{ group }}, color = {{ group }} ) + ) + + # Add title, subtitle, caption, x_title, y_title + g <- g + ggplot2::labs( + title = title, + subtitle = subtitle, + caption = caption, + x = x_title, + y = y_title, + color = group_title, + fill = group_title ) - if (percent) x_labels <- scales::percent else x_labels <- NULL + width <- 0.5 + dodge_width <- 0.5 - pl <- df |> - ggblanket::gg_col(x = {{ x }}, - y = {{ y }}, - col = {{ group }}, - x_title = x_title, - x_labels = x_labels, - y_title = y_title, - col_title = group_title, - alpha = alpha, - width = width, - position = position, - title = title, - subtitle = subtitle, - caption = caption, - col_legend_place = legend_position, - theme = theme_reach( - palette = palette, - reverse = reverse, - family = family, - text_size = text_size, - title_size = title_size, - plot_background_pal = "#FFFFFF", - panel_background_pal = "#FFFFFF", - legend_reverse = legend_rev - ), - ... - ) + # Should the graph use position_fill? + if (position == "stack"){ + g <- g + ggplot2::geom_col( + alpha = alpha, + width = width, + position = ggplot2::position_stack() + ) + } else if (position == "dodge"){ + g <- g + ggplot2::geom_col( + alpha = alpha, + width = width, + position = ggplot2::position_dodge2( + width = dodge_width, + preserve = "single") + ) + } else{ + g <- g + ggplot2::geom_col( + alpha = alpha, + width = width + ) + } + # + # Labels to percent and expand scale + if (percent) { + g <- g + ggplot2::scale_y_continuous( + labels = scales::label_percent( + accuracy = 1, + decimal.mark = ",", + suffix = " %"), + expand = c(0.01, 0.1) + ) + } else { + g <- g + ggplot2::scale_y_continuous(expand = c(0.01, 0.1)) + } - return(pl) + # Because a text legend should always be horizontal, especially for an horizontal bar graph + if (flip){ + g <- g + ggplot2::coord_flip() + } + + # Add text to bars + if (flip) hjust_flip <- 1.5 else hjust_flip <- 0.5 + if (flip) vjust_flip <- 0.5 else vjust_flip <- 1.5 + + if (add_text & position != "dodge") { + rlang::abort("Adding text labels and positions different than dodges as not been implemented yet") + } + + # Add text labels + if (add_text) { + if (percent) { + g <- g + ggplot2::geom_text( + ggplot2::aes( + label = scales::label_percent( + accuracy = 1, + decimal.mark = ",", + suffix = " %")({{ y }}), + group = {{ group }}), + hjust = hjust_flip, + vjust = vjust_flip, + color = "white", + fontface = "bold", + position = ggplot2::position_dodge(width = dodge_width)) + } else { + g <- g + ggplot2::geom_text( + ggplot2::aes( + label = paste0(round({{ y }}), add_text_suffix), + group = {{ group }}), + hjust = hjust_flip, + vjust = vjust_flip, + color = "white", + fontface = "bold", + position = ggplot2::position_dodge(width = dodge_width)) + } + } + + # Add theme + g <- g + theme + + return(g) } diff --git a/R/point.R b/R/point.R index 7e7b551..3ef72c1 100644 --- a/R/point.R +++ b/R/point.R @@ -1,64 +1,81 @@ -#' @title Simple point chart +#' @title Simple bar chart #' #' @param df A data frame. #' @param x A numeric column. #' @param y A character column or coercible as a character column. #' @param group Some grouping categorical column, e.g. administrative areas or population groups. -#' @param palette Palette name from 'pal_reach()'. -#' @param reverse Boolean indicating whether the palette should be reversed. -#' @param family The font family for all plot's texts. Default to "Leelawadee". -#' @param alpha Transparency. -#' @param size Dot size. Default to 1.5. +#' @param flip TRUE or FALSE. Default to TRUE or horizontal bar plot. +#' @param alpha Fill transparency. +#' @param size Point size. #' @param x_title The x scale title. Default to NULL. #' @param y_title The y scale title. Default to NULL. #' @param group_title The group legend title. Default to NULL. #' @param title Plot title. Default to NULL. #' @param subtitle Plot subtitle. Default to NULL. -#' @param caption Caption title string. Default to NULL. -#' @param text_size The size of all text other than the title, subtitle and caption. Defaults to 10. -#' @param title_size The size of the title text. Defaults to 14. -#' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". -#' @param ... Other arguments to be passed to "ggblanket::gg_col" -#' -#' @description `ggblanket` as internals for deciding whether the bar chart is horizontally readable. +#' @param caption Plot caption. Default to NULL. +#' @param theme Whatever theme. Default to theme_reach(). #' #' @return A bar chart #' #' @export -point_reach <- function(df, x, y, group = NULL, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, size = 1.5, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", ...){ +point <- function(df, x, y, group = NULL, flip = TRUE, alpha = 1, size = 1, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, theme = theme_reach()){ - pal <- pal_reach(palette) + # To do : + # - automate bar width and text size, or at least give the flexibility and still center text + # - add facet possibility - if(is.null(pal)) rlang::warn( - c(paste0("There is no palette '", palette, "' for initiative 'reach'. Fallback to ggblanket's default color palette."), - "i" = paste0("Use `pal_reach(show_palettes = T)` to see the list of availabale palettes.") + # Prepare group, x and y names + # if (is.null(x_title)) x_title <- rlang::as_name(rlang::enquo(x)) + # if (is.null(y_title)) y_title <- rlang::as_name(rlang::enquo(y)) + # if (is.null(group_title)) group_title <- rlang::as_name(rlang::enquo(group)) + + # Mapping + g <- ggplot2::ggplot( + df, + mapping = ggplot2::aes(x = {{ x }}, y = {{ y }}, fill = {{ group }}, color = {{ group }} ) ) - pl <- df |> - ggblanket::gg_point(x = {{ x }}, - y = {{ y }}, - col = {{ group }}, - x_title = x_title, - y_title = y_title, - col_title = group_title, - alpha = alpha, - size = size, - title = title, - subtitle = subtitle, - caption = caption, - col_legend_place = legend_position, - theme = theme_reach( - palette = palette, - reverse = reverse, - family = family, - text_size = text_size, - title_size = title_size, - plot_background_pal = "#FFFFFF", - panel_background_pal = "#FFFFFF" - ), - ... + # Add title, subtitle, caption, x_title, y_title + g <- g + ggplot2::labs( + title = title, + subtitle = subtitle, + caption = caption, + x = x_title, + y = y_title, + color = group_title, + fill = group_title + ) + + width <- 0.5 + dodge_width <- 0.5 + + # Should the graph use position_fill? + g <- g + ggplot2::geom_point( + alpha = alpha, + size = size ) - return(pl) + # Labels to percent and expand scale + # if (percent) { + # g <- g + ggplot2::scale_y_continuous( + # labels = scales::label_percent( + # accuracy = 1, + # decimal.mark = ",", + # suffix = " %"), + # expand = c(0.01, 0.1) + # ) + # } else { + # g <- g + ggplot2::scale_y_continuous(expand = c(0.01, 0.1)) + # } + + # # Because a text legend should always be horizontal, especially for an horizontal bar graph + if (flip){ + g <- g + ggplot2::coord_flip() + } + + # Add theme + g <- g + theme + + return(g) } diff --git a/R/theme_reach.R b/R/theme_reach.R index fe5601b..254f5e9 100644 --- a/R/theme_reach.R +++ b/R/theme_reach.R @@ -3,15 +3,25 @@ #' @param palette Palette name from 'pal_reach()'. #' @param discrete Boolean indicating whether color aesthetic is discrete or not. #' @param reverse Boolean indicating whether the palette should be reversed. -#' @param family The font family for all plot's texts. Default to "Leelawadee". +#' @param font_family The font family for all plot's texts. Default to "Leelawadee". +#' @param title_size The size of the title. Defaults to 12. +#' @param title_color Title color. +#' @param title_font_face Title font face. Default to "bold". Font face ("plain", "italic", "bold", "bold.italic"). #' @param text_size The size of all text other than the title, subtitle and caption. Defaults to 10. -#' @param title_size The size of the title text_family. Defaults to 14. -#' @param plot_background_pal The color for the plot background color. Default to white. -#' @param panel_background_pal The color for the panel background color. Default to white. +#' @param text_color Text color. +#' @param text_font_face Text font face. Default to "bold". Font face ("plain", "italic", "bold", "bold.italic"). +#' @param panel_background_color The color for the panel background color. Default to white. #' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". #' @param legend_direction Direction of the legend. Default to "vertical". Can take "vertical" or "horizontal". #' @param legend_reverse Reverse the color in the guide? Default to TRUE. -#' @param ... Additional arguments passed to `ggblanket::gg_theme()`. +#' @param axis_x Boolean. Do you need x-axis? +#' @param axis_y Boolean. Do you need y-axis? +#' @param grid_x Boolean. Do you need major grid lines for x-axis? +#' @param grid_y Boolean. Do you need major grid lines for y-axis? +#' @param grid_x_size X line size. +#' @param grid_y_size Y line size. +#' @param grid_color Grid lines color. +#' @param ... Additional arguments passed to `ggplot2::gg_theme()`. #' #' #' @description Give some reach colors and fonts to a ggplot. @@ -23,33 +33,126 @@ theme_reach <- function( palette = "main", discrete = TRUE, reverse = FALSE, - family = "Leelawadee", + font_family = "Leelawadee", + title_size = 12, + title_color = cols_reach("main_grey"), + title_font_face = "bold", text_size = 10, - title_size = 14, - plot_background_pal = "#FFFFFF", - panel_background_pal = "#FFFFFF", + text_color = cols_reach("main_grey"), + text_font_face = "bold", + panel_background_color = "#FFFFFF", legend_position = "right", legend_direction = "vertical", legend_reverse = TRUE, + axis_x = TRUE, + axis_y = TRUE, + grid_x = FALSE, + grid_y = FALSE, + grid_color = cols_reach("main_lt_grey"), + grid_x_size = 0.1, + grid_y_size = 0.1, ... ) { + # To do : + # - add facet theming + # Basic simple theme - theme_reach <- ggblanket::gg_theme( - text_family = family, - text_size = text_size, - title_size = title_size, - plot_background_pal = plot_background_pal, - panel_background_pal = panel_background_pal) + # theme_reach <- ggplot2::theme_bw() + + theme_reach <- ggplot2::theme( + # Title - design + title = ggplot2::element_text( + family = font_family, + color = title_color, + size = title_size, + face = title_font_face + ), + # Text - design + text = ggplot2::element_text( + family = font_family, + color = text_color, + size = text_size, + face = text_font_face + ), + # Default legend to right position + legend.position = legend_position, + # Defaut legend to vertical direction + legend.direction = legend_direction, + # set panel background color + panel.background = ggplot2::element_rect( + fill = panel_background_color + ), + # Remove minor grid lines + panel.grid.minor.x = ggplot2::element_blank(), + panel.grid.minor.y = ggplot2::element_blank(), + # Remove background for legend key + legend.key = ggplot2::element_blank() + ) + + # Axis lines ? + if (axis_x & axis_y) { + theme_reach <- theme_reach + + ggplot2::theme( + axis.line = ggplot2::element_line(color = text_color)) + } + + if (!axis_x) { + theme_reach <- theme_reach + + ggplot2::theme( + axis.line.x = ggplot2::element_blank(), + axis.ticks.x = ggplot2::element_blank(), + axis.text.x = ggplot2::element_blank()) + } + + if (!axis_y) { + theme_reach <- theme_reach + + ggplot2::theme( + axis.line.y = ggplot2::element_blank(), + axis.ticks.y = ggplot2::element_blank(), + axis.text.y = ggplot2::element_blank()) + } + + # X - major grid lines + if (!grid_x) theme_reach <- theme_reach + + ggplot2::theme( + panel.grid.major.x = ggplot2::element_blank() + ) else theme_reach <- theme_reach + + ggplot2::theme( + panel.grid.major.x = ggplot2::element_line( + color = grid_color, + linewidth = grid_y_size) + ) + + # Y - major grid lines + if (!grid_y) theme_reach <- theme_reach + + ggplot2::theme( + panel.grid.major.y = ggplot2::element_blank() + ) else theme_reach <- theme_reach + + ggplot2::theme( + panel.grid.major.y = ggplot2::element_line( + color = grid_color, + linewidth = grid_y_size) + ) + + # Other parameters + theme_reach <- theme_reach + ggplot2::theme(...) - # Default legend to right position - theme_reach <- theme_reach + - ggplot2::theme(legend.position = legend_position) + # Check if palette is an actual existing palette + pal <- pal_reach(palette) - # Defaut legend to vertical direction - theme_reach <- theme_reach + - ggplot2::theme(legend.direction = legend_direction) + if(is.null(pal)) { + rlang::warn( + c( + paste0("There is no palette '", palette, "' for initiative 'reach'. Fallback to REACH main palette."), + "i" = paste0("Use `pal_reach(show_palettes = TRUE)` to see the list of availabale palettes.") + ) + ) + + palette <- "main" + + } # Add reach color palettes by default # (reversed guide is defaulted to TRUE for natural reading)