library(tidyverse)
library(ggplot2)
library(ggtilecal)
make_empty_month_days(c("2024-01-05", "2024-06-30")) |>
gg_facet_wrap_months(unit_date,
.geom = list(
geom_tile(color = "grey70",
fill = "transparent"),
geom_text(nudge_y = 0.25,
color = "#6a329f")),
.theme = list(
theme_bw_tilecal(),
theme(strip.background = element_rect(fill = "#d9d2e9")))
)
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the ggtilecal package.
## Please report the issue at <https://github.com/cynthiahqy/ggtilecal>.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
make_empty_month_days(c("2024-01-05", "2024-06-30")) |>
gg_facet_wrap_months(unit_date)
args(gg_facet_wrap_months)
## function (.events_long, date_col, locale = NULL, week_start = NULL,
## nrow = NULL, ncol = NULL, .geom = list(geom_tile(color = "grey70",
## fill = "transparent"), geom_text(nudge_y = 0.25)), .scale_coord = list(scale_y_reverse(),
## scale_x_discrete(position = "top"), coord_fixed(expand = TRUE)),
## .theme = list(theme_bw_tilecal()), .other = list())
## NULL
body(gg_facet_wrap_months)
## {
## cal_data <- calc_calendar_vars(fill_missing_units(.events_long,
## {
## {
## date_col
## }
## }), {
## {
## date_col
## }
## })
## base_plot <- ggplot2::ggplot(cal_data, mapping = aes_string(x = "TC_wday_label",
## y = "TC_month_week", label = "TC_mday")) + facet_wrap(c("TC_month_label"),
## axes = "all_x", nrow = nrow, ncol = ncol) + labs(y = NULL,
## x = NULL) + .geom + .scale_coord + .theme + .other
## base_plot
## }
gg_facet_wrap_months <- function(...){
## Data Helpers
cal_data <- .events_long |>
fill_missing_units({{ date_col }}) |>
calc_calendar_vars({{ date_col }})
## Plot Construction
base_plot <- cal_data |>
ggplot2::ggplot(mapping = aes_string(
x = "TC_wday_label",
y = "TC_month_week",
label = "TC_mday"
)) +
facet_wrap(c("TC_month_label"), axes = "all_x", nrow = nrow, ncol = ncol) +
labs(y = NULL, x = NULL) +
.geom +
.scale_coord +
.theme +
.others
base_plot
}
gg_facet_wrap_months(
.events_long,
date_col,
locale = NULL,
week_start = NULL,
nrow = NULL,
ncol = NULL,
.geom = list(
geom_tile(color = "grey70", fill = "transparent"),
geom_text(nudge_y = 0.25)
),
.scale_coord = list(
scale_y_reverse(),
scale_x_discrete(position = "top"),
coord_fixed(expand = TRUE)),
.theme = list(theme_bw_tilecal()),
.other = list()
)
## Error in (function (arg) : object 'date_col' not found
The component list arguments are initialised with sensible defaults,
and inherit aesthetic mappings from the “fixed” internal components. The
“fixed” components are the “improper” part of the solution, as they
could probably be replaced by new ggplot2 Stat and Facet
objects.
List arguments bind together user inputs that all go into the same
place inside the helper function (e.g. elements in .geom
are added before .scale_coord, which comes before
.theme and the final the catch-all .other).
This design allow users to leverage the consistent syntax
ggplot2 when specifying customisations. The user specified
ggplot2 components are passed directly into the ggplot
building portion of the helper function, avoiding the need for ad-hoc
and plot-specific customisation arguments.
gg_facet_wrap_months <- function(...){
## Data Helpers
cal_data <- .events_long |>
fill_missing_units({{ date_col }}) |>
calc_calendar_vars({{ date_col }})
## Plot Construction
base_plot <- cal_data |>
ggplot2::ggplot(mapping = aes_string(
x = "TC_wday_label",
y = "TC_month_week",
label = "TC_mday"
)) +
facet_wrap(c("TC_month_label"), axes = "all_x", nrow = nrow, ncol = ncol) +
labs(y = NULL, x = NULL) +
.geom +
.scale_coord +
.theme +
.others
base_plot
}
The example below shows an example customisation using the component arguments:
library(ggplot2)
library(ggtilecal)
make_empty_month_days(c("2024-01-05", "2024-06-30")) |>
gg_facet_wrap_months(unit_date,
.geom = list(
geom_tile(color = "grey70",
fill = "transparent"),
geom_text(nudge_y = 0.25,
color = "#6a329f")),
.theme = list(
theme_bw_tilecal(),
theme(strip.background = element_rect(fill = "#d9d2e9")))
)
## Error in (function (arg) : object 'date_col' not found
This design also supports using geoms from other packages without
depending on those packages directly, (i.e. ggiraph is not
a dependency of ggtilecal). Additional layers can be
included in the .geom, or added as normal using
+:
# remotes::install_github("cynthiahqy/ggtilecal")
library(ggiraph)
library(ggplot2)
library(ggtilecal)
gi <- demo_events_gpt |>
reframe_events(startDate, endDate) |>
gg_facet_wrap_months(unit_date) +
geom_text(aes(label = event_emoji), nudge_y = -0.25, na.rm = TRUE) +
geom_tile_interactive(
aes(
tooltip = paste(event_title),
data_id = event_id
),
alpha = 0.2,
fill = "transparent",
colour = "grey80"
)
## Error in (function (arg) : object 'date_col' not found
girafe(ggobj = gi)
## Error: object 'gi' not found
In addition to exposing the ggplot2 components as list
arguments, I also document the data preparation steps that the plot
helper function is performing:
#' Make Monthly Calendar Facets
#'
#' Generates calendar with monthly facets by:
#' - Padding event list with any missing days via `fill_missing_units()`
#' - Calculating variables for calendar layout via `calc_calendar_vars()`
#' - Returning a ggplot object as per Details.
and how the ggplot2 recipe works:
#' Returns a ggplot with the following fixed components using calculated layout variables:
#' - `aes()` mapping:
#' - `x` is day of week,
#' - `y` is week in month,
#' - `label` is day of month
#' - `facet_wrap()` by month
#' - `labs()` to remove axis labels for calculated layout variables
#'
#' and default customisable components:
#' - `geom_tile()`, `geom_text()` to label each day which inherit calculated variables
#' - `scale_y_reverse()` to order day in month correctly
#' - `scale_x_discrete()` to position weekday labels
#' - `coord_fixed()` to square each tile
#' - `theme_bw_tilecal()` to apply sensible theme defaults
#'
and how to modify the plot:
#' To modify components alter the `.geom` and `.scale_coord`,
#' which inherit the calculate layout mapping by default
#' (via the ggplot2 `inherit.aes` argument).
#'
#' To add components use the ggplot `+` function as normal,
#' or pass components to the `.other` argument.
#' This can be used to add interactive geoms (e.g. from `ggiraph`)
#'
#' To modify the theme, use the ggplot `+` function as normal,
#' or add additional elements to the list in `.theme`.
#'
#' To remove any of the optional components,
#' set the argument to any empty `list()`
ggplot2 Plot HelpersTo summarise my opinionated take on how you should write plot helper functions:
ggplot2 recipes.