I would like to color the date axis labels considering some conditions. Here is an example:
# Libraries
library("ggplot2")
library("lubridate")
# Create data
data0 <- data.frame(dt = seq(as.Date('2022-01-01'),as.Date('2022-01-20'),1))
data0$y <- runif(length(data0$dt))
head(data0)
### dt y
### 1 2022-01-01 0.99842049
### 2 2022-01-02 0.10663102
### 3 2022-01-03 0.04824916
### 4 2022-01-04 0.49312740
### 5 2022-01-05 0.01445124
### 6 2022-01-06 0.96767266
# Define color red for Saturday and Sunday
lab_col <- with(data0, ifelse(wday(dt) %in% c(1,7),"red","black"))
ggplot(data0,aes(dt,y)) +
geom_line() +
scale_x_date(date_breaks = "1 day"
, date_labels = "%Y-%m-%d (%a)"
) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.3, hjust=1, colour=lab_col))
This gives what I expected:
But it also gives this message:
Warning message:
Vectorized input to `element_text()` is not officially supported.
Results may be unexpected or may change in future versions of ggplot2.
Indeed, using my original data the wrong weekdays are colored red.
I found a possible solution here using ggtext
:
data0$dt2 <- with(data0, paste0("<i style = 'color: "
, lab_col
, ";'>"
, dt
, " (",wday(dt, label=TRUE),")"
, "</i>"
)
)
head(data0)
### dt y dt2
### 1 2022-01-01 0.99842049 <i style = 'color: red;'>2022-01-01 (Sa)</i>
### 2 2022-01-02 0.10663102 <i style = 'color: red;'>2022-01-02 (So)</i>
### 3 2022-01-03 0.04824916 <i style = 'color: black;'>2022-01-03 (Mo)</i>
### 4 2022-01-04 0.49312740 <i style = 'color: black;'>2022-01-04 (Di)</i>
### 5 2022-01-05 0.01445124 <i style = 'color: black;'>2022-01-05 (Mi)</i>
### 6 2022-01-06 0.96767266 <i style = 'color: black;'>2022-01-06 (Do)</i>
library("ggtext")
ggplot(data0,aes(dt2,y)) +
geom_line() +
scale_x_date(date_breaks = "1 day") +
theme(axis.text.x = element_markdown(angle = 90, vjust = 0.3, hjust=1))
But this gives me this error:
Error: Invalid input: date_trans works with objects of class Date only
This makes sense since dt2
is not a date. The SO-example from above link consider factor variables. How can I use the power of ggtext
with date as x-variable?
You're right about why ggtext doesn't work, but we can work around this.
You can use a function for the labels
argument of the scale. This can be a function that does the label formatting for you.
# Libraries
library("ggplot2")
library("lubridate")
library("ggtext")
# Create data
data0 <- data.frame(dt = seq(as.Date('2022-01-01'),as.Date('2022-01-20'),1))
data0$y <- runif(length(data0$dt))
ggplot(data0,aes(dt,y)) +
geom_line() +
scale_x_date(
date_breaks = "1 day",
labels = function(x) {
col <- ifelse(wday(x) %in% c(1, 7), "red", "black")
lab <- strftime(x, format = "%Y-%m-%d (%a)")
glue::glue("<span style = 'color:{col}'>{lab}</span>")
}
) +
theme(axis.text.x = element_markdown(angle = 90, vjust = 0.3, hjust=1))
Created on 2022-08-26 by the reprex package (v2.0.0)