I started to make a calendar in Excel, but thought it might be easy to do in R instead. (Note: I'm aware of various heatmap calendar packages but I prefer to use ggplot2
.) Ultimately I want to make a calendar that shows 12 months starting from a given date, with each month as a small box showing 4 or 5 weeks on the y-axis (week 1 at the top, week 4 or 5 at the bottom) and the days of the week (starting from Monday) along the x-axis.
I thought this would be a 15-minute job (create data for all months, format a bit using reshape
then use facet_wrap
) but ran into problems almost immediately as the plot below shows - the days of the month are not in order, although the days of the week seem okay. Ordering data in R is my nemesis; I really should get a handle on this. Anyway, the image below shows what I have so far and the code is below that. This is just a fun project, not urgent, but any help and/or embellishments welcome.
require(ggplot2)
require(scales)
require(lubridate)
date.start <- as.Date('2013-09-01')
date.end <- date.start + months(1)
mydf <- data.frame(mydate = seq(as.Date(date.start),
as.Date(date.end) - days(1),
by = 'day'))
mydf$month <- month(mydf$mydate)
mydf$week <- week(mydf$mydate)
mydf$day <- day(mydf$mydate)
mydf$dow <- as.factor(format(mydf$mydate, format = "%a"))
levels(mydf$dow) <- c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')
ggplot(mydf, aes(x = dow, y = as.factor(week))) +
geom_tile(colour = "black", fill = "white", label = mydf$day) +
geom_text(label = mydf$day, size = 4, colour = "black") +
scale_x_discrete(expand = c(0,0)) +
theme(axis.ticks = element_blank()) +
theme(axis.title.y = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(panel.background = element_rect(fill = "transparent"))+
theme(legend.position = "none") +
theme()
Create the week.f
column with levels in reverse order. We have used "%U"
(assuming US convention but if you want the UK convention use "%W"
and also change the order of the factor levels of dow
). Also we have allowed arbitrary date input calculating the start of the month and have simplified the ggplot
call slightly.
library(ggplot2)
input <- as.Date("2013-09-11") # input date
st <- as.Date(cut(input, "month")) # calculate start of month
dates31 <- st + 0:30 # st and next 30 dates (31 in all)
dates <- dates31[months(dates31) == months(st)] # keep only dates in st's month
week.ch <- format(dates, "%U") # week numbers
mydf <- data.frame(
day = as.numeric(format(dates, "%d")),
week.f = factor(week.ch, rev(unique(week.ch))),
dow = factor(format(dates, "%a"), c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))
)
ggplot(mydf, aes(x = dow, y = week.f)) +
geom_tile(colour = "black", fill = "white") +
geom_text(label = mydf$day, size = 4) +
scale_x_discrete(expand = c(0,0)) +
theme(axis.ticks = element_blank()) +
theme(axis.title = element_blank()) +
theme(panel.background = element_rect(fill = "transparent"))+
theme(legend.position = "none")
By the way, there is a cal
function in the TeachingDemos package that can construct a one month calendar using classic graphics.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With