{"id":13711135,"url":"https://github.com/EvaMaeRey/ggcalendar","last_synced_at":"2025-05-06T20:32:03.435Z","repository":{"id":43780080,"uuid":"471486605","full_name":"EvaMaeRey/ggcalendar","owner":"EvaMaeRey","description":"and interface for plotting calendar months with date input in ggplot2","archived":false,"fork":false,"pushed_at":"2024-09-03T19:44:33.000Z","size":14351,"stargazers_count":35,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-10T03:23:57.250Z","etag":null,"topics":["calendar","ggplot2","r","rstats"],"latest_commit_sha":null,"homepage":"https://evamaerey.github.io/ggcalendar/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EvaMaeRey.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-18T19:07:07.000Z","updated_at":"2024-09-03T19:44:36.000Z","dependencies_parsed_at":"2024-01-17T16:08:12.479Z","dependency_job_id":"39b1f8a2-d34e-4774-95ec-41c88467f7c4","html_url":"https://github.com/EvaMaeRey/ggcalendar","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvaMaeRey%2Fggcalendar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvaMaeRey%2Fggcalendar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvaMaeRey%2Fggcalendar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvaMaeRey%2Fggcalendar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EvaMaeRey","download_url":"https://codeload.github.com/EvaMaeRey/ggcalendar/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224528341,"owners_count":17326347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendar","ggplot2","r","rstats"],"created_at":"2024-08-02T23:01:04.845Z","updated_at":"2024-11-13T21:31:33.854Z","avatar_url":"https://github.com/EvaMaeRey.png","language":"R","funding_links":[],"categories":["Plot layers"],"sub_categories":[],"readme":"---\noutput: \n  github_document:\n    toc: TRUE\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\",\n  warning = F,\n  message = F\n)\n```\n\n\n\n# ggcalendar\n\n\u003c!-- badges: start --\u003e\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)\n\u003c!-- badges: end --\u003e\n\n*Note: This README walks through package rational and contains the code that defines proposed package functions and in addition to first-cut testing. [TLDR - Jump to traditional readme content](#traditional-readme)*\n\nHere's a proposal for creating calendars with ggplot2 via Stat extension.   \n\nWhen using calendars, 'when?' and 'where?' are the same question! So, ggcalendar introduces a new positional aesthetic: 'date'.  Let's *put* things on the calendar!\n\nIn this proposed package, we'll specify the position of a calendar event calendar using dates as the required aesthetic: `aes(date = my_variable_of_dates)`!  Then you can use layers function `stat_calendar()` and derivative geom functions `geom_text_calendar`, `geom_tile_calendar` and `geom_point_calendar` to place specific grobs/mark in the plot space. \n\nUnder the hood, the compute_group functions finds the x and y position for the date in the month (x is day in week and y is week in month). Faceting by month is used to prevent over-plotting.  Note:  automatic faceting by month via ggcalendar() function presupposes that your variable is also named 'date'.\n\nOther possible directions would be to calculate x and y based on date in month *and* on month - instead of relying on faceting by month.  Furthermore, a dedicated Coord could be created (Teun's thought).  Then maybe dates would just feed generically in as the 'x' aes - this sounds cool!\n\n\n```{r setup}\n# library(ggcalendar)\nlibrary(ggplot2)\nlibrary(lubridate)\nlibrary(tidyverse)\n```\n\n\n``` r\n# install.packages(\"devtools\")\ndevtools::install_github(\"EvaMaeRey/ggcalendar\")\n```\n\n\n# Step 00. Convenience functions, dates vectors to data frames.\n\nBecause ggplot2's diet is consists solely of dataframes, we create a number of convenience functions that will help us produce dataframes with column 'date' we can feed into ggplot2.\n\n```{r}\nknitrExtra:::chunk_to_r(\"df_functions\")\n```\n\n```{r df_functions}\n#' Title\n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_today \u003c- function(){\n\n  data.frame(date = Sys.Date())\n\n}\n\n#' Title\n#'\n#' @param date \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_day \u003c- function(date = NULL){\n  \n  if(is.null(date)){date \u003c- Sys.Date()}\n\n  data.frame(date = date)\n\n}\n\n\n#' Title\n#'\n#' @param start_date \n#' @param end_date \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_dates_interval \u003c- function(start_date, end_date){\n\n  data.frame(date = as.Date(start_date):as.Date(end_date) |\u003e\n    as.Date())\n\n}\n\n#' Title\n#'\n#' @param month \n#' @param year \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_month \u003c- function(month = NULL, year = NULL){\n\n  if(is.null(month)){\n    \n    date \u003c- Sys.Date()\n    month \u003c- lubridate::month(date) \n  }\n   \n  if(is.numeric(month)){ \n    \n    month \u003c- stringr::str_pad(month, width = 2, pad = \"0\")\n    \n  }\n  \n    if(is.null(year)){\n    \n    date \u003c- Sys.Date()\n    year \u003c- lubridate::year(date)\n    }\n\n  \n  paste0(year,\"-\", month, \"-01\") |\u003e\n    lubridate::as_date() -\u003e\n    start_date\n\n  start_date |\u003e lubridate::ceiling_date(unit = \"month\") -\u003e\n    end_date\n\n    data.frame(date = \n                 df_dates_interval(start_date, \n                                       end_date - lubridate::days(1)))\n\n}\n\n#' Title\n#'\n#' @param date \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_week \u003c- function(date = NULL){\n\n  if(is.null(date)){date \u003c- Sys.Date()}\n\n  start_date \u003c- lubridate::floor_date(date, unit = \"week\")\n  end_date \u003c- lubridate::ceiling_date(date, unit = \"week\")\n\n  data.frame(date = df_dates_interval(start_date, \n                        end_date - lubridate::days(1)) )\n\n}\n\n#' Title\n#'\n#' @param date \n#'\n#' @return\n#' @export\n#'\n#' @examples\nreturn_df_hours_week \u003c- function(date = NULL){\n\n  if(is.null(date)){date \u003c- Sys.Date()}\n\n  start_date \u003c- lubridate::floor_date(date, unit = \"week\")\n\n  data.frame(date = (start_date + lubridate::hours(1:(24*7-1))))\n\n}\n\n#' Title\n#'\n#' @param year \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndf_year \u003c- function(year = NULL){\n\n  if(is.null(year)){year \u003c-  lubridate::year(Sys.Date())}\n\n  paste0(year, \"-01-01\") |\u003e\n    lubridate::as_date() -\u003e\n  start_date\n\n  start_date |\u003e lubridate::ceiling_date(unit = \"year\") -\u003e\n    end_date\n\n    data.frame(date = \n                 df_dates_interval(start_date, \n                                       end_date - lubridate::days(1)))\n    \n}\n```\n\n\n## Examples\n\nLet's have a look at some of these.\n\n```{r}\ndf_today()\n\ndf_day()\n\ndf_dates_interval(start_date = \"2024-10-02\", end_date = \"2024-10-04\")\n\ndf_week()\n\ndf_year() |\u003e head()\n\ndf_month() |\u003e head()\n\nreturn_df_hours_week() |\u003e head()\n```\n\n# Step 1 \u0026 2. Compute: from date to x/y, \u0026 define StatCalendar\n\nThe computation that we want to be done under the hood relates to translating the here-to-fore unknown positional aesthetic 'date' to the first-class 'x' and 'y' positional aesthetic mappings, as well as variables that can be used in faceting (month).\n\n\n```{r}\nknitrExtra:::chunk_to_r(\"get_week_of_month\")\n```\n\nAs a pre-step to computing many useful variables from our date variable, we focus on this (currently messy) conversion of vectors of dates to week of the month.  \n\n```{r get_week_of_month}\nget_week_of_month \u003c- function(x){\n  \n  (- lubridate::wday(x) + lubridate::day(x)) %/% \n    7 + 1 +\n    ifelse(lubridate::wday(lubridate::floor_date(lubridate::as_date(x), \"month\")) == 1, 0, 1)\n  \n}\n```\n\nNext, we'll define a compute group function.  A number of variables are created by parsing our date variable. \n\nThen, we'll pass all this computation to define a new ggproto object StatCalendar.  For maximum flexibility, our compute function doesn't create ggplot2 core aesthetic channels 'x', 'y', and 'label' variables, but instead uses the default_aes field to state what should be first interpreted as x, y and label (thoughts? Maybe only 'label' should be managed like this).  \n\n\n```{r}\nknitrExtra:::chunk_to_r(\"compute_group_calendar\")\n```\n\n```{r compute_group_calendar}\ncompute_group_calendar \u003c- function(data, scales){\n\n  data |\u003e\n    dplyr::mutate(wday = lubridate::wday(.data$date)) |\u003e\n    dplyr::mutate(wday_abbr = lubridate::wday(.data$date, label = TRUE, abbr = TRUE)) |\u003e\n    dplyr::mutate(week_of_month = get_week_of_month(.data$date)) |\u003e\n    dplyr::mutate(day = lubridate::day(.data$date)) |\u003e\n    dplyr::mutate(year = lubridate::year(.data$date) - 2018) |\u003e\n    dplyr::mutate(month_abbr = lubridate::month(.data$date, abbr = TRUE, label = TRUE)) |\u003e\n    dplyr::mutate(hour = lubridate::hour(.data$date)) |\u003e\n    dplyr::mutate(year_academic =  lubridate::year(.data$date) +\n                    ifelse(lubridate::month(date) \u003e\n                             6, 1, 0)) |\u003e\n    dplyr::mutate(month_academic_abbr = .data$month_abbr |\u003e\n                    factor(levels = c(\"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n                                      \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\")))\n\n}\n\nStatCalendar \u003c- ggplot2::ggproto(`_class` = \"StatCalendar\",\n                                 `_inherit` = ggplot2::Stat,\n                                 required_aes = c(\"date\"),\n                                 compute_group = compute_group_calendar,\n                                 default_aes = ggplot2::aes(x = ggplot2::after_stat(wday),\n                                                            y = ggplot2::after_stat(week_of_month),\n                                                            label = ggplot2::after_stat(day)))\n\n\nStatWeekly \u003c- ggplot2::ggproto(`_class` = \"StatCalendar\",\n                               `_inherit` = ggplot2::Stat,\n                               required_aes = c(\"date\"),\n                               compute_group = compute_group_calendar,\n                               default_aes = ggplot2::aes(x = ggplot2::after_stat(wday),\n                                                          y = ggplot2::after_stat(hour),\n                                                          label = ggplot2::after_stat(hour)))\n```\n\n## Test it out\n\nOkay, let's see how our compute and Stat work in action!\n\n```{r}\ndf_week() |\u003e\n  compute_group_calendar()\n\ndf_month() |\u003e\n  ggplot() + \n  aes(date = date) + \n  geom_text(stat = StatCalendar)\n```\n\n# Step 3.  Let's write a user-facing function `stat_calendar()`\n\n```{r}\nknitrExtra:::chunk_to_r(\"a_stat_calendar\")\n```\n\n\n```{r a_stat_calendar}\n#' Title\n#'\n#' @param mapping \n#' @param data \n#' @param geom \n#' @param position \n#' @param na.rm \n#' @param show.legend \n#' @param inherit.aes \n#' @param ... \n#'\n#' @return\n#' @export\n#'\n#' @examples\nstat_calendar \u003c- function(mapping = NULL, \n                          data = NULL,\n                          geom = \"text\",\n                          position = \"identity\", \n                          na.rm = FALSE,\n                          show.legend = NA,\n                          inherit.aes = TRUE, ...) {\n  ggplot2::layer(\n    stat = StatCalendar, # proto object from Step 2\n    geom = geom, # inherit other behavior\n    data = data,\n    mapping = mapping,\n    position = position,\n    show.legend = show.legend,\n    inherit.aes = inherit.aes,\n    params = list(na.rm = na.rm, ...)\n  )\n}\n\n\n```\n\n### Test `stat_calendar`\n\n```{r}\ndf_year() |\u003e \n  ggplot() + \n  aes(date = date) +\n  stat_calendar(color = \"grey\") + \n  facet_wrap(~month(date, label = T,  abbr = T)) + \n  scale_y_reverse()\n```\n\n# aliasing and convenience\n\nTo give the user a better sense of what they'll see when using stat_calendar we create the alias, 'geom_text_calendar()'.  \n\n```{r}\nknitrExtra:::chunk_to_r(\"geom_text_calendar\")\n```\n\n```{r geom_text_calendar}\n#' Title\n#'\n#' @param ... \n#'\n#' @return\n#' @export\n#'\n#' @examples\ngeom_text_calendar \u003c- function(...){stat_calendar(geom = \"text\", ...)}\n\n#' Title\n#'\n#' @param ... \n#'\n#' @return\n#' @export\n#'\n#' @examples\ngeom_point_calendar \u003c- function(...){stat_calendar(geom = \"point\", ...)}\n\n#' Title\n#'\n#' @param ... \n#'\n#' @return\n#' @export\n#'\n#' @examples\ngeom_tile_calendar \u003c- function(...){stat_calendar(geom = \"tile\", ...)}\n```\n\n\n# `defaults_calendar` \u0026 `ggcalendar()` Thinking about set of scales/coords etc, that gives you a nice calendar (to wrap up into defaults)\n\nIn our test of stat_calendar, we see cumbersomeness.  Below, we consider even more ggplot2 decision that would make our plot easier to consume and more beautiful.\n\n\n\n```{r}\nday_labels = c(\"S\", \"M\", \"T\", \"W\", \"T\", \"F\", \"S\")\n\ndf_year() |\u003e \n  ggplot() + \n  aes(date = date) +\n  stat_calendar(color = \"grey\") +\n    ggplot2::aes(date = date) +\n    ggplot2::scale_y_reverse(breaks = 5:0, \n                             expand = c(0,0), \n                             limits = c(6.5, 0.5)) +\n    ggplot2::scale_x_continuous(breaks = 1:7, \n                                labels = day_labels,\n                                limits = c(.5, 7.5), \n                                expand = c(0,0)\n                                ) +\n    ggplot2::facet_wrap(~lubridate::month(date, abbr = T, label = T), scales = \"free\") +\n    ggplot2::labs(x = NULL, y = NULL) +\n    ggplot2::theme(axis.text.y = ggplot2::element_blank(),\n          axis.ticks.y = ggplot2::element_blank(),\n          axis.ticks.x = ggplot2::element_blank()) +\n    ggplot2::theme(panel.grid.major = ggplot2::element_blank()) + \n    ggplot2::geom_blank()\n\n```\n\n## `theme_calendar`, `defaults_calendar` \u0026 `ggcalendar()`\n\nThen, we bundle these up into defaults_calendar, which can be quickly added for converting to a more polished and readable calendar.\n\n```{r}\nknitrExtra::chunk_to_dir(\"theme_grey_calendar\")\n```\n\n\n```{r theme_grey_calendar}\n#' Title\n#'\n#' @param ... \n#'\n#' @return\n#' @export\n#'\n#' @examples\ntheme_grey_calendar \u003c- function(...){\n\n  theme_grey(...) %+replace%\n    ggplot2::theme(\n      axis.text.y = ggplot2::element_blank(),\n      axis.ticks.y = ggplot2::element_blank(),\n      axis.ticks.x = ggplot2::element_blank(),\n      axis.title = element_blank()) +\n    ggplot2::theme(\n      panel.grid.major = ggplot2::element_blank())\n  \n}\n\n\nscale_y_calendar \u003c- function(...){ggplot2::scale_y_reverse(breaks = 6:0, \n                             expand = c(0,0), \n                             limits = c(6.5, 0.5), ...)}\n\nscale_x_calendar \u003c- function(day_labels = c(\"M\", \"T\", \"W\", \"T\", \"F\", \"S\", \"S\"), ...){\n  \n    ggplot2::scale_x_continuous(breaks = 1:7, \n                                labels = day_labels,\n                                limits = c(.5, 7.5), \n                                expand = c(0,0), ...)}\n\nfacet_calendar \u003c- function(...){\n  \n  ggplot2::facet_wrap(~lubridate::month(date, abbr = T, label = T), \n                      scales = \"free\",...)\n  \n}\n\n\ngeom_calendar_blank \u003c- function(...){\n  \n  stat_calendar(geom = \"blank\", ...)\n  \n}\n\n\n```\n\n```{r}\nknitrExtra:::chunk_to_r(\"defaults_calendar\")\n```\n\n```{r defaults_calendar}\n#' Title\n#'\n#' @param day_labels \n#'\n#' @return\n#' @export\n#'\n#' @examples\ndefaults_calendar \u003c- function(day_labels = c(\"M\", \"T\", \"W\", \"T\", \"F\", \"S\", \"S\")){\n  \n  week_start \u003c- getOption(\"lubridate.week.start\", 7)\n  \n  if(week_start != 1){day_labels \u003c- day_labels[c(week_start:7, 1:(week_start-1))]}\n\n  list(scale_y_calendar(),\n       scale_x_calendar(day_labels = day_labels),\n       facet_calendar(),\n       theme_grey_calendar(),\n       stat_calendar(geom = \"blank\")\n       )\n  \n}\n```\n\n\nLet's check it out...\n\n\n```{r}\ndf_week() |\u003e \n  ggplot() +\n  aes(date = date) + \n  stat_calendar() + \n  defaults_calendar()\n\ndf_year() |\u003e \n  ggplot() +\n  aes(date = date) + \n  stat_calendar() + \n  defaults_calendar()\n\n```\n\nFurthermore, we provide ggcalendar as an alternative point of entry into the ggplot framework.  The default data frame is even included (the current calendar year), so a full calendar will print with no additional specification.\n\n```{r}\nknitrExtra:::chunk_to_r(\"ggcalendar\")\n```\n\n```{r ggcalendar}\n#' Title\n#'\n#' @param dates_df \n#' @param day_labels \n#' @param geom \n#' @param color \n#' @param size \n#' @param alpha \n#'\n#' @return\n#' @export\n#'\n#' @examples\nggcalendar \u003c- function(dates_df = df_year(), \n                       day_labels = c(\"M\", \"T\", \"W\", \"T\", \"F\", \"S\", \"S\"), \n                       geom = \"text\", \n                       color = \"grey35\",\n                       size = 3,\n                       alpha = 1){\n  \n    my_layer \u003c- stat_calendar(geom = geom, \n                              color = color, \n                              ggplot2::aes(date = date), \n                              size = size, \n                              alpha = alpha, \n                              show.legend = F) \n    \n  ggplot2::ggplot(data = dates_df) +\n  defaults_calendar(day_labels = day_labels) +\n  ggplot2::aes(date = date) +\n  my_layer\n\n  }\n```\n\nLet's check it out!\n\n```{r}\nggcalendar()\n\nggcalendar() + \n  stat_calendar(geom = \"point\", \n                data = df_week(),\n                color = \"darkred\",\n                size = 5,\n                alpha = .5)\n\noptions(lubridate.week.start = 1)\n\nggcalendar() + \n  stat_calendar(geom = \"point\", \n                data = df_week(),\n                color = \"darkred\",\n                size = 5,\n                alpha = .5)\n```\n\n## More \n\n```{r}\nlibrary(magrittr)\nggcalendar() +\n   # remember default data in ggcalendar() is current year of dates\n  aes(date = date) +\n  geom_tile_calendar(data = . %\u003e%  \n                      filter(wday(date) == 3),  \n                      fill = \"blue\",  \n                      alpha = .2) +\n  labs(title = \"When to do #TidyTuesday in 2024\") +\n  stat_calendar(label = \"X\",\n                color = \"darkred\",\n                size = 5,\n                data = df_dates_interval(\n                  \"2024/01/01\", Sys.Date() - days(1)),\n                 alpha = .35)\n```\n\n\n\n```{r}\ndf_month(year = 2023, month = 2) |\u003e \n  ggcalendar()\n\ndf_month(year = 2023, month = 2) |\u003e \nggcalendar()\n\ndf_month(year = 2023, month = 2) |\u003e \nggcalendar(geom = \"blank\") + \n  aes(date = date) + \n  geom_text_calendar(label = \"Another\\nday...\", # override default\n                     size = 4)\n\ndf_month(year = 2023, month = 2) |\u003e \nggcalendar() + \n  aes(date = date) + \n  geom_text_calendar() + \n  geom_point_calendar(data = . %\u003e% filter(wday(date) %in% 2:6),\n                      alpha = .2,\n                      size = 5,\n                      color = \"cadetblue\") + \n  theme(panel.background = element_rect(fill = \"beige\"))\n\nlibrary(ggplot2)\n\ndf_dates_interval(\"2023-09-01\", \"2023-12-31\") |\u003e \n  ggcalendar()\n```\n\n```{r example}\n## basic example code\nc(\"2022-03-19\", \"2022-04-09\", \"2022-05-07\", \n  \"2022-06-11\", \"2022-07-16\") %\u003e% \n  tibble(date = .) |\u003e \n  mutate(date = date %\u003e% as_date) |\u003e \n  mutate(future = Sys.Date() \u003c date) -\u003e\nevents\n\ndf_year(2022) |\u003e \n  ggcalendar() +\n  aes(date = date) +\n  geom_text_calendar() + \n  geom_point_calendar(data = events,\n                      aes(color = future),\n                      size = 8, \n                      alpha = .5,\n                      show.legend = F) +\n  labs(title = \"nu2ggplot2X^2sion, 2022\")\n```\n\n\n\n\n\n# NYC flights Example\n\n\u003e Airline on-time data for all flights departing NYC in 2013. Also includes useful 'metadata' on airlines, airports, weather, and planes.\n\n\n\nData inspiration:  https://twitter.com/rappa753/status/1545729747774308354 @rappa753\n\n```{r}\n\n# example \nnycflights13::flights |\u003e \n  ungroup() |\u003e \n  mutate(date = as.Date(time_hour)) |\u003e \n  filter(year(date) == 2013) |\u003e \n  count(date) |\u003e \n  ggcalendar() +\n  aes(date = date) +\n  geom_point_calendar(data = . %\u003e% tibble(), aes(size = n, \n                          color = n), \n                      alpha = .7, show.legend = F) + \n  scale_color_viridis_c(option = \"inferno\", direction = 1) + \n  scale_size(range = c(3,8)) +\n  geom_text_calendar(aes(label = n), size = 2) + \n  NULL\n```\n\n\n---\n\n\n# Births example\n\n```{r}\nbirths \u003c- \"https://raw.githubusercontent.com/EvaMaeRey/tableau/9e91c2b5ee803bfef10d35646cf4ce6675b92b55/tidytuesday_data/2018-10-02-us_births_2000-2014.csv\"\n\nreadr::read_csv(births) |\u003e \n  mutate(month = stringr::str_pad(month, 2, pad = \"0\"),\n         date_of_month = str_pad(date_of_month, 2, pad = \"0\")) |\u003e \n  mutate(date = paste(year, month, date_of_month, sep = \"-\") |\u003e as_date()) |\u003e \n  filter(year == 2012) |\u003e \n  ggcalendar() + \n  aes(date = date) + \n  geom_point_calendar(alpha = .4) +\n  aes(size = births) +\n  aes(color = births) +\n  scale_color_viridis_c() +\n  guides(\n    colour = guide_legend(\"Births\"),\n    size = guide_legend(\"Births\")\n ) + \n  geom_point_calendar(data = data.frame(date =\n                                      as_date(\"2012-12-25\")),\n                      size = 5, color = \"red\", shape = 21)\n  \n```\n\n---\n\n# data defaults to calendar year and aes(date = date)\n\nThe following feels a little weird to me, but is allowed.  \n\nA grammar of graphics fundamental is that a statistical graphic are composed of geometries/marks that take on aesthetics (color, position, size), to represent a variable.\n\nBelow we aren't aren't fully stating these specifications; which feels a bit funny; I would not recommend this as a starting point.  \n\n```{r}\nggcalendar() + \n geom_text_calendar()\n```\n\n\n---\n\n\n\n\n\n---\n\n\n\n\n# Minimal Viable Packaging\n\n```{r, eval = T}\nusethis::use_package(\"lubridate\")\nusethis::use_package(\"ggplot2\")\nusethis::use_package(\"dplyr\")\nusethis::use_package(\"stringr\")\n```\n\n```{r, eval = F}\ndevtools::check()\ndevtools::install(pkg = \".\", upgrade = \"never\") \n```\n\n\n\n# Traditional README\n\n\n```{r, eval = T}\nrm(list = ls())\nlibrary(ggcalendar)\nlibrary(tidyverse)\noptions(lubridate.week.start = 1) # start on Monday\n\nggcalendar() + \n  labs(title = \"Calendar: 2024\")\n\nggcalendar() + \n  geom_tile_calendar(\n    data = df_week(),\n    fill = \"red\",\n    alpha = .25) + \n  geom_point_calendar(\n    data = df_today(),\n    color = \"goldenrod3\", shape = 21,\n    size = 8, stroke = 1.5\n    )\n\n\n# example \nnycflights13::flights |\u003e \n  ungroup() |\u003e \n  mutate(date = as.Date(time_hour)) |\u003e \n  filter(year(date) == 2013) |\u003e \n  count(date) |\u003e \n  ggcalendar(geom = \"blank\") +\n      aes(date = date) +\n      geom_tile_calendar(\n        aes(fill = n),\n        alpha = .7, show.legend = F) + \n      scale_fill_viridis_c(option = \"inferno\", \n                            direction = 1) + \n      scale_size(range = c(3,8)) +\n      geom_text_calendar(aes(label = n), \n                         size = 2) + \n      NULL\n\n```\n\n```{r}\ncontrast \u003c- function(colour) {\n  out   \u003c- rep(\"grey35\", length(colour))\n  light \u003c- farver::get_channel(colour, \"l\", space = \"hcl\")\n  out[light \u003c 50] \u003c- \"grey80\"\n  out\n}\n  \naes_autocontrast_color_on_fill \u003c- aes(colour = after_scale(contrast(fill)))\n\nlibrary(ggcalendar)\n\nnhl_player_births \u003c- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-01-09/nhl_player_births.csv')\n\n\nnhl_player_births |\u003e \n  mutate(date = birth_date %\u003e% \n           str_replace(\"....\", \"2024\") %\u003e% \n           as_date()) %\u003e% \n  count(date) %\u003e% \n  ggcalendar(geom = \"blank\") +  \n  aes(date = date, # date is positional aes\n      fill = n) +\n  labs(title = \"Number of NHL Player Birthdays by day 1879-2005\\nas celebrated in 2024\") +\n  geom_tile_calendar(alpha = .85, linewidth = 0) +\n  scale_fill_viridis_c() \n\nlast_plot() +\n  aes(label = n) + \n  geom_text_calendar(size = 3) +\n  aes_autocontrast_color_on_fill + \n  guides(fill = \"none\")\n  \n\n```\n\n\n```{r example2, eval = F}\n## basic example code\ndf_month(month = \"2022-07\") |\u003e \n  head()\n\nreturn_dates_interval(start_date = \"2022-07-01\", \n                      end_date = \"2022-08-31\") |\u003e \n  ggcalendar() +\n  aes(date = date) +\n  geom_text_calendar(size = 8) + \n  geom_point_calendar(data = . %\u003e% filter(date == \"2022-07-04\"),\n                      size = 8, \n                      alpha = .5) +\n  geom_point_calendar(data = . %\u003e% filter(date \u003c Sys.Date()),\n                      size = 10, shape = \"x\")\n```\n\n\n---\n\n```{r}\nknitr::knit_exit()\n\n```\n\n# more ideas\n\n```{r}\n#' #' Title\n#' #'\n#' #' @param data\n#' #' @param scales\n#' #'\n#' #' @return\n#' #' @export\n#' #'\n#' #' @examples\n#' #' return_dates_year(1999) %\u003e%\n#' #' head() %\u003e%\n#' #' compute_group_calendar()\n#' #'\n#' compute_group_weekly \u003c- function(data, scales){\n#'\n#'   data %\u003e%\n#'     dplyr::mutate(num_day_of_week = lubridate::wday(.data$date)) %\u003e%\n#'     dplyr::mutate(day_of_week = lubridate::wday(.data$date, label = TRUE, abbr = TRUE)) %\u003e%\n#'     dplyr::mutate(week_of_month = (- lubridate::wday(.data$date) + lubridate::day(.data$date)) %/% 7 + 1 +\n#'                     ifelse(lubridate::wday(lubridate::floor_date(lubridate::as_date(.data$date), \"month\")) == 1, -1, 0)\n#'                   ) %\u003e%\n#'     dplyr::mutate(date_of_month = lubridate::day(.data$date)) %\u003e%\n#'     dplyr::mutate(which_year = lubridate::year(.data$date) - 2018) %\u003e%\n#'     dplyr::mutate(month = lubridate::month(.data$date, abbr = TRUE, label = TRUE)) %\u003e%\n#'     dplyr::mutate(hour = lubridate::hour(.data$date)) %\u003e%\n#'     dplyr::mutate(academic_year =  lubridate::year(.data$date) +\n#'                     ifelse(lubridate::month(date) \u003e\n#'                              6, 1, 0)) %\u003e%\n#'     dplyr::mutate(academic_month = .data$month %\u003e%\n#'                     factor(levels = c(\"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n#'                                       \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\")))\n#'\n#' }\n#'\n#' StatWeekly \u003c- ggplot2::ggproto(`_class` = \"StatWeekly\",\n#'                                  `_inherit` = ggplot2::Stat,\n#'                                  required_aes = c(\"date\"),\n#'                                  compute_group = compute_group_weekly,\n#'                                  default_aes = ggplot2::aes(x = ggplot2::after_stat(day_of_week %\u003e% as.numeric()),\n#'                                                             y = ggplot2::after_stat(hour),\n#'                                                             label = ggplot2::after_stat(date_of_month)))\n#'\n```\n\n\n```{r}\n#' Title\n#'\n#' @param dates_df\n#'\n#' @return\n#' @export\n#'\n#' @examples\n#' library(lubridate)\n#' library(dplyr)\n#' library(ggplot2)\n#' library(magrittr)\n#'\n#' ggweekly() +\n#' geom_text_weekly()\n#'\n#' ggweekly() +\n#' geom_text_weekly(color = \"grey35\") +\n#' labs(title = \"When to do #TidyTuesday in 2022\") +\n#' geom_text_weekly(label = \"X\",\n#'                   data = data.frame(date = seq(as.Date(\"2022/01/01\"),\n#'                   as.Date(\"2022/04/18\"), \"days\")))\n#'\nggweekly \u003c- function(dates_df = return_hours_week(), day_labels = c(\"M\", \"T\", \"W\", \"T\", \"F\", \"S\", \"S\")){\n\n  week_start \u003c- getOption(\"lubridate.week.start\", 7)\n  \n  if(week_start != 1){day_labels \u003c- day_labels[c(week_start:7, 1:(week_start-1))]}\n\n  ggplot2::ggplot(data = dates_df) +\n    ggplot2::aes(date = date) +\n    ggplot2::scale_y_reverse(\n      breaks = 7:21,\n                             expand = c(0,0),\n                             limits = c(21 + .5,\n                                        7 - .5),\n\n                             ) +\n    ggplot2::scale_x_continuous(breaks = 1:7, labels = day_labels,\n                                limits = c(.5, 7.5),expand = c(0,0)\n\n                                #position = \"top\"\n                                ) +\n    ggplot2::facet_wrap(~epiweek(date), scales = \"free\") +\n    ggplot2::labs(x = NULL, y = NULL) +\n    ggplot2::theme(#axis.text.y = ggplot2::element_blank(),\n          axis.ticks.y = ggplot2::element_blank(),\n          axis.ticks.x = ggplot2::element_blank()) +\n    ggplot2::theme(panel.grid.major = ggplot2::element_blank()) +\n    ggplot2::geom_blank() +\n    # theme(strip.placement = \"outside\") +\n    NULL\n\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEvaMaeRey%2Fggcalendar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEvaMaeRey%2Fggcalendar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEvaMaeRey%2Fggcalendar/lists"}