8

I am sure this is an easy one but I couldn't find a solution from other posts.

If I run this:

test <- data.frame(dates = as.Date(c("2016-10-31","2016-11-30", "2016-12-31", "2017-01-31")), 
                   values = c(1, 2, 3, 4))
ggplot(test, aes(x = dates, y = values)) +
  geom_bar(position="stack", stat = "identity") + 
  scale_x_date(breaks = date_breaks("1 months"),labels = date_format("%b-%y"))

I get this:

enter image description here

As you can appreciate, all the dates on the X axis are moved forward to the following month. I tried to use the scales package as suggested elsewhere but it didn't change a thing.

I can get away with this by tweaking the date using:

test$dates <- as.Date(format(test$dates, "%Y-%m-1"))

which delivers this (without using the scale_x_date bit):

enter image description here

but I am sure there is an elegant way to circumvent the problem.

Matteo Castagna
  • 472
  • 3
  • 13
  • 1
    The dates aren't moved forward, the breaks are just at the start of the new month and your bars are plotted 1 day before that. If you look closely you can see that the bars aren't exactly above the breaks, they're shifted slightly to the left of each break. – Marijn Stevering Mar 23 '17 at 10:53
  • It looks true. Unfortunately it doesn't sort out the problem. What is also odd (see the updated OP), the chart based on "1/m/y" places the label right in the middle. So I am not sure about your analysis. – Matteo Castagna Mar 23 '17 at 11:42

2 Answers2

4

I have run into this problem myself when doing monthly time series charts. My solution: add in a vector of dates into the "breaks = " section.

I.e.

scale_x_date(breaks = test$dates, labels = date_format("%b-%y"))

Note: When I tried "data_breaks" (like your code), I was not able to get it to work under a number of different permutations. The vector of dates only works with "breaks", not "data_breaks"

  ggplot(test, aes(x = dates, y = values)) +
      geom_bar(position="stack", stat = "identity") + 
      scale_x_date(breaks = test$dates, labels = date_format("%b-%y"))

P.s. This is my first attempt at answering a question here. I know that the question is old, but hopefully this will help someone!

Piranha
  • 116
  • 6
2

The labels are correct when you transform dates with as.POSIXct and use scale_x_datetime instead of scale_x_date (no idea why though):

ggplot(test, aes(x = as.POSIXct(dates), y = values)) +
  geom_bar(position="stack", stat = "identity") + 
  scale_x_datetime(breaks = date_breaks("1 months"), labels = date_format("%b-%y"))

enter image description here

erc
  • 10,113
  • 11
  • 57
  • 88
  • Really confused as to why this works, because the bars are still slightly ahead of the breaks, so the breaks are still at the start of the next month, but take the label of the previous month. – Marijn Stevering Mar 23 '17 at 11:06
  • Even funnier: it doesn't do anything for me. Applying the `as.POSIXct()` to dates and then using `scale_x_datetime` as suggested, I keep getting the same chart (with the change of the x label). Any chance this as to do with TZ somehow? – Matteo Castagna Mar 23 '17 at 11:25
  • Possibly, to be honest, dates and timezones in R will forever be a mystery to me, so I'm afraid I can't help :/ – erc Mar 23 '17 at 11:28