148 lines
4.8 KiB
R
148 lines
4.8 KiB
R
#' @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 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 wrap Should x-labels be wrapped? Number of characters.
|
|
#' @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 title Plot title. Default to NULL.
|
|
#' @param subtitle Plot subtitle. Default to NULL.
|
|
#' @param caption Plot caption. Default to NULL.
|
|
#' @param add_text TRUE or FALSE. Add the value as text.
|
|
#' @param add_text_threshold_display Minimum value to add the text label.
|
|
#' @param add_text_color Text color.
|
|
#' @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 <- function(df, x, y, group = NULL, flip = TRUE, percent = TRUE, wrap = NULL, position = "dodge", alpha = 1, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, width = 0.9, add_text = FALSE, add_text_threshold_display = 5, add_text_color = "white", add_text_suffix = "", theme = theme_reach()){
|
|
|
|
# To do :
|
|
# - automate bar width and text size, or at least give the flexibility and still center text
|
|
# - add facet possibility
|
|
|
|
# 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
|
|
)
|
|
|
|
width <- width
|
|
dodge_width <- width
|
|
|
|
# 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))
|
|
}
|
|
|
|
if (!is.null(wrap)) {
|
|
g <- g + ggplot2::scale_x_discrete(labels = scales::label_wrap(wrap))
|
|
}
|
|
|
|
# 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) {
|
|
|
|
df <- dplyr::mutate(df, "y_threshold" = ifelse({{ y }} >= add_text_threshold_display, {{ y }}, NA ))
|
|
|
|
if (percent) {
|
|
g <- g + ggplot2::geom_text(
|
|
data = df,
|
|
ggplot2::aes(
|
|
label = scales::label_percent(
|
|
accuracy = 1,
|
|
decimal.mark = ",",
|
|
suffix = " %")(!!rlang::sym("y_threshold")),
|
|
group = {{ group }}),
|
|
hjust = hjust_flip,
|
|
vjust = vjust_flip,
|
|
color = add_text_color,
|
|
fontface = "bold",
|
|
position = ggplot2::position_dodge(width = dodge_width))
|
|
} else {
|
|
g <- g + ggplot2::geom_text(
|
|
data = df,
|
|
ggplot2::aes(
|
|
label = paste0(round(!!rlang::sym("y_threshold")), add_text_suffix),
|
|
group = {{ group }}),
|
|
hjust = hjust_flip,
|
|
vjust = vjust_flip,
|
|
color = add_text_color,
|
|
fontface = "bold",
|
|
position = ggplot2::position_dodge(width = dodge_width))
|
|
}
|
|
}
|
|
|
|
# Add theme
|
|
g <- g + theme
|
|
|
|
return(g)
|
|
}
|