visualizeR/R/point.R
2025-07-01 19:49:47 +02:00

212 lines
5.3 KiB
R

#' @title Simple scatterplot
#'
#' @param df A data frame.
#' @param x A quoted numeric column.
#' @param y A quoted numeric column.
#' @param group Some quoted grouping categorical column, e.g. administrative areas or population groups.
#' @param facet Some quoted grouping categorical column.
#' @param facet_scales Character. Either "free" (default) or "fixed" for facet scales.
#' @param x_rm_na Remove NAs in x?
#' @param y_rm_na Remove NAs in y?
#' @param group_rm_na Remove NAs in group?
#' @param facet_rm_na Remove NAs in facet?
#' @param add_color Add a color to points (if no grouping).
#' @param add_color_guide Should a legend be added?
#' @param flip TRUE or FALSE.
#' @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 Plot caption. Default to NULL.
#' @param theme_fun Whatever theme. Default to theme_point(). NULL if no theming needed.
#'
#' @inheritParams scale_color_visualizer_discrete
#'
#' @export
point <- function(
df,
x,
y,
group = "",
facet = "",
facet_scales = "free",
x_rm_na = TRUE,
y_rm_na = TRUE,
group_rm_na = TRUE,
facet_rm_na = TRUE,
add_color = color("cat_5_main_1"),
add_color_guide = TRUE,
flip = TRUE,
alpha = 1,
size = 2,
x_title = NULL,
y_title = NULL,
group_title = NULL,
title = NULL,
subtitle = NULL,
caption = NULL,
theme_fun = theme_point(),
scale_fill_fun = scale_fill_visualizer_discrete(),
scale_color_fun = scale_color_visualizer_discrete()
) {
#------ Checks
# df is a data frame
checkmate::assert_data_frame(df)
# x and y and group are character
checkmate::assert_character(x, len = 1)
checkmate::assert_character(y, len = 1)
checkmate::assert_character(group, len = 1)
# x and y are columns in df
checkmate::assert_choice(x, colnames(df))
checkmate::assert_choice(y, colnames(df))
if (group != "") {
checkmate::assert_choice(group, colnames(df))
}
# x_rm_na, y_rm_na and group_rm_na are logical scalar
checkmate::assert_logical(x_rm_na, len = 1)
checkmate::assert_logical(y_rm_na, len = 1)
checkmate::assert_logical(group_rm_na, len = 1)
checkmate::assert_logical(facet_rm_na, len = 1)
# facet_scales is a character scalar in c("free", "fixed")
checkmate::assert_choice(facet_scales, c("free", "fixed"))
# flip is a logical scalar
checkmate::assert_logical(flip, len = 1)
# alpha is a numeric scalar between 0 and 1
checkmate::assert_numeric(alpha, lower = 0, upper = 1, len = 1)
# size is a numeric scalar
checkmate::assert_numeric(size, len = 1)
# x and y are numeric
if (!any(c("numeric", "integer") %in% class(df[[x]]))) {
rlang::abort(paste0(x, " must be numeric."))
}
if (!any(c("numeric", "integer") %in% class(df[[y]]))) {
rlang::abort(paste0(y, " must be numeric."))
}
#----- Data wrangling
# facets over group
if (group != "" && facet != "" && group == facet) {
rlang::warn("'group' and 'facet' are the same identical.")
}
# remove NAs using base R
if (x_rm_na) {
df <- df[!(is.na(df[[x]])), ]
}
if (y_rm_na) {
df <- df[!(is.na(df[[y]])), ]
}
if (group != "" && group_rm_na) {
df <- df[!(is.na(df[[group]])), ]
}
if (facet != "" && facet_rm_na) {
df <- df[!(is.na(df[[facet]])), ]
}
# prepare aes
if (group != "") {
g <- ggplot2::ggplot(
df,
mapping = ggplot2::aes(
x = !!rlang::sym(x),
y = !!rlang::sym(y),
fill = !!rlang::sym(group),
color = !!rlang::sym(group)
)
)
} else {
g <- ggplot2::ggplot(
df,
mapping = ggplot2::aes(
x = !!rlang::sym(x),
y = !!rlang::sym(y)
)
)
}
# 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
)
# facets
# facets
if (facet != "") {
if (flip) {
g <- g +
ggplot2::facet_grid(
rows = ggplot2::vars(!!rlang::sym(facet)),
scales = facet_scales,
space = if (facet_scales == "free") "free_y" else "fixed"
)
} else {
g <- g +
ggplot2::facet_grid(
cols = ggplot2::vars(!!rlang::sym(facet)),
scales = facet_scales,
space = if (facet_scales == "free") "free_x" else "fixed"
)
}
}
# Should the graph use position_fill?
if (group != "") {
g <- g +
ggplot2::geom_point(
alpha = alpha,
size = size
)
} else {
g <- g +
ggplot2::geom_point(
alpha = alpha,
size = size,
color = add_color
)
}
if (flip) {
g <- g + ggplot2::coord_flip()
}
# Remove guides for legend if !add_color_guide
if (!add_color_guide) {
g <- g + ggplot2::guides(fill = "none", color = "none")
}
# Add theme
if (!is.null(theme_fun)) {
g <- g + theme_fun
}
# Add scale fun
if (!is.null(scale_fill_fun)) {
g <- g + scale_fill_fun
}
if (!is.null(scale_color_fun)) {
g <- g + scale_color_fun
}
return(g)
}