0

I am trying to create a plot with dates on the x-axis in R using ggplot2 and the scales library. The problem is, when I am using the command scale_x_datetime(breaks = date_breaks(width = "1 day"), labels=date_format("%e. %b")), the breaks seems to be OK, but the labels are one day behind. So, for the data point for 1st of May, the label is the 30th of April.

I guess it is because I use the scale for discrete value, and it is intended for continuous data. Anyway, how can I make sure that the label for the 1st of May says 1st of May?

enter image description here

library(ggplot2)
library(scales)

start <- "2015-05-01 00:00:00"
end <- "2015-05-10 00:00:00"

df <- data.frame(
  x = seq(as.POSIXct(start), as.POSIXct(end), by = "1 day"),
  y = runif(10, 0, 20)
)

ggplot(df, aes(x, y)) +
  geom_point() +
  scale_x_datetime(breaks = date_breaks(width = "1 day"), labels=date_format("%e. %b"))

Solution with help from @Deena

breaks.index <- match(unique(format(df$x, "%d. %b")), format(df$x, "%d. %b"))

ggplot(df, aes(x, y)) + geom_point() + 
  scale_x_datetime(breaks = df$x[breaks.index],
  labels = format(df$x[breaks.index], "%e. %b")) 
Christoffer
  • 643
  • 1
  • 6
  • 22

1 Answers1

1

Honestly, I don't know why we are getting 30April on the axis. But following is a work around:

#works 
ggplot(df, aes(x, y)) + geom_point() + 
  scale_x_datetime(breaks = date_breaks(width = "day")) 

#doesn't work
ggplot(df, aes(x, y)) + geom_point() + 
  scale_x_datetime(breaks = date_breaks(width = "day") , labels = date_format("%d. %b")) 

#Work around
ggplot(df, aes(x, y)) + geom_point() + 
  scale_x_datetime(breaks =df$x , labels = format(df$x, "%d. %b")) 
  • The problem is when my data changes to hourly values for instance. Then I will have a huge amount of labels. – Christoffer Oct 15 '15 at 10:57
  • @Christoffer You can always index df$x and format(df$x, "%d. %b"). If you get hourly data and need daily labels, try to go for something like : `myBreak.index = which(unique( format (df$x, "%d. %b")) ` , then use `df$x[myBreak.index]` and `format(df$x, "%d. %b") [myBreak.index]` –  Oct 15 '15 at 11:14
  • Great @Deena. I had to use `match()` instead of `which()`. See the edit in the original question. – Christoffer Oct 15 '15 at 12:35
  • Great that it works nor @Christoffer ! Another thing that I've just noticed, if your data time series has more than a year value, include the year value in the indexing also. ie: `breaks.index <- match(unique(format(df$x, "%d. %b %Y")), format(df$x, "%d. %b %Y")) ` –  Oct 15 '15 at 14:06