Skip to contents

The goal of ggtilecal is to easily produce calendar layouts using ggplot2 tile and text geoms, while retaining some customisation.

Installation

You can install the development version of ggtilecal like so:

# install.packages("remotes")
remotes::install_github("cynthiahqy/ggtilecal")

Examples

Empty Calendar

library(ggtilecal)
make_empty_month_days(c("2024-01-05", "2024-04-04")) |>
  gg_facet_wrap_months(unit_date)

Customising empty calendars

Layers in .geom inherit the internally generated calendar layout mapping variables. gg_facet_wrap_months() provides uses lists of sensible default layers that can be easily modified. Customise the look of each calendar tile using geom_tile(), and the text number labels using geom_text().

library(ggplot2)
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")))
                       )

Adding more layers to the calendar: Event emojis!

Prepare event details:

demo_events_overlap
#> # A tibble: 10 × 7
#> # Rowwise: 
#>    event_id title    start      end        duration emoji details               
#>       <int> <chr>    <date>     <date>        <int> <chr> <chr>                 
#>  1        1 Event 1  2024-01-08 2024-01-10        3 🐟    Adipiscing mauris et …
#>  2        2 Event 2  2024-01-16 2024-01-17        2 🐩    Sit aliquam feugiat p…
#>  3        3 Event 3  2024-01-24 2024-01-24        1 🐨    Lorem placerat sagitt…
#>  4        4 Event 4  2024-02-22 2024-02-27        6 🐚    Ipsum mollis fermentu…
#>  5        5 Event 5  2024-03-04 2024-03-04        1 🦟    Consectetur malesuada…
#>  6        6 Event 6  2024-03-11 2024-03-16        6 🐛    Sit bibendum porta ut…
#>  7        7 Event 7  2024-03-12 2024-03-17        6 🦣    Lorem cursus sem cubi…
#>  8        8 Event 8  2024-03-14 2024-03-18        5 🦖    Adipiscing fames magn…
#>  9        9 Event 9  2024-03-16 2024-03-17        2 🐣    Amet ligula sociis ve…
#> 10       10 Event 10 2024-03-26 2024-03-31        6 🐈‍⬛    Sit ridiculus id maec…

Reshape event data into “long” form, which in this context refers to having one row per day of an event. In this example, if multiple events (i.e. 6,7,8,9) expand to the same days, we select only one event to plot an emoji for.

events_long <- demo_events_overlap |>
  reframe_events(start, end) |>
  dplyr::slice_min(order_by = duration, n = 1, by = unit_date)
events_long
#> # A tibble: 29 × 6
#>    event_id title   duration emoji details                            unit_date 
#>       <int> <chr>      <int> <chr> <chr>                              <date>    
#>  1        1 Event 1        3 🐟    Adipiscing mauris et augue dapibu… 2024-01-08
#>  2        1 Event 1        3 🐟    Adipiscing mauris et augue dapibu… 2024-01-09
#>  3        1 Event 1        3 🐟    Adipiscing mauris et augue dapibu… 2024-01-10
#>  4        2 Event 2        2 🐩    Sit aliquam feugiat primis duis s… 2024-01-16
#>  5        2 Event 2        2 🐩    Sit aliquam feugiat primis duis s… 2024-01-17
#>  6        3 Event 3        1 🐨    Lorem placerat sagittis vehicula … 2024-01-24
#>  7        4 Event 4        6 🐚    Ipsum mollis fermentum in risus r… 2024-02-22
#>  8        4 Event 4        6 🐚    Ipsum mollis fermentum in risus r… 2024-02-23
#>  9        4 Event 4        6 🐚    Ipsum mollis fermentum in risus r… 2024-02-24
#> 10        4 Event 4        6 🐚    Ipsum mollis fermentum in risus r… 2024-02-25
#> # ℹ 19 more rows

We can create an empty calendar that spans the months of the events:

events_long |>
  gg_facet_wrap_months(unit_date)

But maybe we want to indicate which days are event days:

emoji_cal <- events_long |>
  gg_facet_wrap_months(unit_date) +
  geom_text(aes(label = emoji), nudge_y = -0.25, na.rm = TRUE)
emoji_cal

Additional rows are introduced within gg_facet_wrap_months() to plot the non-event days. Specify na.rm = TRUE on subsequent layers to silence the warning. This silently removes both the missing values generated when calculating calendar variables AS WELL AS any “true” missing values originating in events_long.

If the emojis are not rendering, try changing your graphics device. For knitr output this can be controlled using the dev chunk option. For previews in RStudio, change Settings > General > Graphics (e.g. to AGG). To save use something like ggplot2::ggsave("ggtilecal.png", emoji_cal, height=3, width=9, dpi=300)

Add interactive elements

We can also add interactive tile layers using ggigraph:

library(ggiraph)
library(ggplot2)

gi <- events_long |>
  gg_facet_wrap_months(unit_date) +
  geom_text(aes(label = emoji), nudge_y = -0.25, na.rm = TRUE) +
  geom_tile_interactive(
        aes(
            tooltip = paste(title),
            data_id = event_id
        ),
        alpha = 0.2,
        fill = "transparent",
        colour = "grey80"
    )

if(interactive()){
  ggiraph::girafe(ggobj = gi)
}