R ggplot geom_tile uneven vertical spacing for dates

Viewed 388
set.seed(1990)

ID <- rep(LETTERS,each = 12)
n <- rep(round(runif(12,1,10)), 26)
datetime <- rep(seq(as.POSIXct("2020-01-01"), as.POSIXct("2020-12-01"), by="month"), 26)
datetime <- lubridate::date(datetime)
dataset <- tibble(ID, datetime, n)

ggplot(dataset 
       ,
       aes(x=datetime,y= reorder(ID, n),fill=n))+
  geom_tile(color = 'gray') +
  scale_x_date(expand = c(0,0),breaks = seq(as.Date("2014-07-01"), as.Date("2020-12-01"), by = "1 month"), date_labels = "%Y %b", name = 'Monthly') 

enter image description here

It seems that the spacing is determined by the length of days for a particular month, which is not really useful in this context.

The temporary solution I found is by converting the dates into factor, but still doesn't seem the best because the horizontal spaces are also uneven.

dataset$datetime <- factor(dataset$datetime)

ggplot(dataset 
       ,
       aes(x=datetime,y= reorder(ID, n),fill=n))+
  geom_tile(color = 'gray')

enter image description here

But I will then lose on the ability to make use of scale_x_date() for labeling purpose

> ggplot(dataset 
+        ,
+        aes(x=datetime,y= reorder(ID, n),fill=n))+
+   geom_tile(color = 'gray') +
+   scale_x_date(expand = c(0,0),breaks = seq(as.Date("2014-07-01"), as.Date("2020-12-01"), by = "1 month"), date_labels = "%Y %b", name = 'Monthly') 
Error: Invalid input: date_trans works with objects of class Date only

What I hope to achieve is this perfect square with equal spacing across all tiles as below. enter image description here

1 Answers

It's a bit of a hack, but how about changing the date to a factor in the aes() call with zoo::as.yearmon(datetime). Then you can use coord_equal():

library(zoo)
ggplot(dataset, aes(y = as.factor(zoo::as.yearmon(datetime)),
                    x = reorder(ID, n), fill=n)) +
  geom_tile(color = 'gray') + labs(x = "Factor", y = "Date") +
  coord_equal() 

enter image description here

If you need more format control, add in a call to format:

ggplot(dataset ,aes(y = reorder(as.factor(format(zoo::as.yearmon(datetime),"%Y %b")),
                                zoo::as.yearmon(datetime)),
                    x = reorder(ID, n), fill = n)) +
  geom_tile(color = 'gray') + labs(x = "Factor", y = "Date") +
  coord_equal() 

enter image description here

Related