1

I am trying to display all month values on my x-axis, which is formatted as a "yearmon" variable

My data are structured as follows:

Print data example

dput(collective_action_monthly[1:4, ])

ouptut:

structure(list(collective_action = structure(c(2L, 2L, 2L, 2L
), .Label = c("0", "1"), class = "factor"), treatment_details = c("pre", 
"pre", "pre", "pre"), month_year = structure(c(2011.41666666667, 
2011.75, 2011.83333333333, 2011.91666666667), class = "yearmon"), 
    n = c(22L, 55L, 15L, 207L), collective_action_percentage = c(0.0124223602484472, 
    0.031055900621118, 0.00846979107848673, 0.116883116883117
    ), am = structure(c(2L, 2L, 2L, 2L), .Label = c("post", "pre"
    ), class = "factor")), class = c("grouped_df", "tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -4L), groups = structure(list(
    treatment_details = "pre", .rows = structure(list(1:4), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -1L), .drop = TRUE))

This my code to visualize the trend using bar graphs by month:

ggplot(data = collective_action_monthly, aes(x = month_year, y = collective_action_percentage)) +
    geom_bar(stat = "identity", position=position_dodge()) + 
    scale_fill_grey() +
    ylab("percentage") + 
    theme(text=element_text(size=10)) + 
    theme(plot.title = element_text(size = 10, face = "bold")) +
    scale_y_continuous(labels = percent_format(accuracy = 1)) +
   theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  theme_bw()

which produces: enter image description here

However, rather than only showing three months in the x-axis, I would like to show all months. I also tried adding "scale_x_continuous(labels = 0:14, breaks = 0:14) " to the code above, but it still does not display months: enter image description here

Ideally, I would like to produce a graph as the one below, but with months instead of years.

enter image description here

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
maldini1990
  • 279
  • 2
  • 11

2 Answers2

2

ggplot doesn't have a yearmon scale built in--looks like the zoo package does, but it doesn't have a convenient way to specify "breaks every month"--so I would suggest converting to Date class and using scale_x_date. I've deleted most of your theme stuff to make the changes I've made more obvious (the theming didn't seem relevant to the issue).

ggplot(data = collective_action_monthly, aes(x = as.Date(month_year), y = collective_action_percentage)) +
    geom_bar(stat = "identity", position=position_dodge()) + 
    scale_fill_grey() +
    scale_x_date(date_breaks = "1 month", date_labels = "%b %Y") +
    ylab("percentage") + 
  theme_bw()

enter image description here

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • Presumably `yearmon` is from the `zoo` package, which as you guessed has a `scale_x_yearmon`. I've added an answer to demonstrate, but I think if I were doing it myself, I would probably convert to standard dates too. – Allan Cameron Aug 04 '22 at 13:32
  • 1
    I wouldn't. That would make the X axis irregularly spaced so it is basically wrong. – G. Grothendieck Aug 04 '22 at 13:34
  • 1
    @G.Grothendieck I'm confused--do you think this answer creates a misleading or wrong plot? Could you help me understand what's wrong about it? – Gregor Thomas Aug 04 '22 at 13:52
  • 1
    To me, it looks identical to the `scale_x_yearmon` version in Allan's answer, except that axis limits match the range of the data. – Gregor Thomas Aug 04 '22 at 13:55
  • It looks similar but the analyses associated with it likely all assume regularly spaced data. It is actually easier to do it right rather than switching systems just for the axis. – G. Grothendieck Aug 04 '22 at 14:05
  • I'm not suggesting changing the class for any analysis--and I don't see an easier way to adjust the plot axis as OP asks. – Gregor Thomas Aug 04 '22 at 14:10
  • Unless I'm mistaken, Allan's answer keeps the `yearmon` class but puts it on a regularly spaced axis with `breaks = seq(2011.25, 2012, 1/12)`. Less convenient code--needing to explicitly set the limits--for the same result. – Gregor Thomas Aug 04 '22 at 14:12
  • Well, if you don't like the default obviously you will have to specify something else. Also I don't see any good reason to start at April when there is no data for April. and May. If we can omit these months then specifying `scale_x_yearmon(n = 12)` or any large number for n is all that is needed. – G. Grothendieck Aug 04 '22 at 17:10
  • `scale_x_yearmon(n = 12)` looks great, you should add it as an answer! – Gregor Thomas Aug 04 '22 at 18:12
2

The zoo packages includes scale_x_yearmon, so you can do:

library(zoo)
library(ggplot2)

ggplot(data = collective_action_monthly, 
       aes(x = month_year, y = collective_action_percentage)) +
    geom_col(position = position_dodge(preserve = "single")) +
    scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                       name = "percentage") +
    scale_x_yearmon(breaks = seq(2011.25, 2012, 1/12),
                    limits = c(2011.25, 2012)) +
    theme_bw(base_size = 10) +
    theme(plot.title = element_text(size = 10, face = "bold"),
          axis.text.x = element_text(angle = 90, vjust = 0.5)) 

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87