Danielle Travassos
Danielle Travassos

Reputation: 151

ggplot2: x axis breaks doesn't work with 7 days breaks

I'm trying to figure it out why this function for x axis breaks works perfectly for 2 to 6 days breaks, but gives me an error when I change to 7 days (Error: breaks and labels must have the same length). Thank you

Data Frame

library(tidyverse)

    df <- data.frame(date = seq(as.Date("2019-01-01"), as.Date("2019-12-31"), by = "day"))
    df$counts <-sample(seq(from = 20, to = 50, by = 5), size = 365, replace = TRUE)

    df<- df %>%
    mutate(date = as.Date(date),
           counts = as.numeric(counts))

Code

    breaks_daily = seq(from = min(df$date), to = max(df$date), by = "1 day")

    # Then make the 7 days interval labels 
    labels_7_days = format(seq(from = min(df$date), to = max(df$date), by = "7 days"), "%b-%d")
    labels_final = c(sapply(labels_7_days, function(x) {
      c(x, rep("", 6))
    }))
    #

     if ((length(breaks_daily) %% 7) == 0) {
        labels_final <- labels_final
      } else {
        labels_final<- labels_final[-length(labels_final)]
     }

    myplot <- ggplot(df, 
                       aes(y = counts, x = date)) +
      geom_bar(stat = "identity", position = "dodge", fill = "#99CCFF", width=1) +
      labs(x="Date", y="Quantity of Fruits") + 

      scale_x_date(labels = labels_final, breaks = breaks_daily, expand=c(0,0)) +
      scale_y_continuous(limits = c(0, 70), 
                         breaks = seq(0, 70, 10),
                         expand = c(0, 0)) +
      ggtitle(paste0("Figure 2: Fruits Example" )) +


      theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 35),
            axis.text.y = element_text(size = 35),
            axis.text = element_text(size = 35),
            axis.title = element_text(size = 40, face="bold"),
            axis.title.y = element_text(vjust = -2), 
            axis.title.x =  element_text(vjust = -1),
            axis.ticks.length = unit(.5, "cm"))


    myplot

Upvotes: 1

Views: 206

Answers (1)

tjebo
tjebo

Reputation: 23757

Not a direct answer to your question, but why don't you just use the inbuilt functionality? Sometimes it is not necessary to reinvent the wheel... ?

library(tidyverse)
df <- data.frame(date = seq(as.Date("2019-01-01"), as.Date("2019-12-31"), by = "day"))
df$counts <-sample(seq(from = 20, to = 50, by = 5), size = 365, replace = TRUE)

ggplot(df, aes(y = counts, x = date)) +
  geom_col() +
  scale_x_date(date_breaks = "1 week",date_labels = "%b %d")+
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

update

Here how to keep the ticks in-between (although I don't think your visualisation gains a lot with it) You need to bring the two vectors to the same length. When using your label creator, you are creating six empty spaces for each week until the maximum (and including it!), then of course making "too many labels". Just subset the vector by using only the length of your breaks.

P.S. geom_col is identical to geom_bar(stat = "identity") , and in your example you don't need position = position_dodge, as you have no group defined. This argument only makes sense when you are dodging by a group.

library(tidyverse)
df <- data.frame(date = seq(as.Date("2019-01-01"), as.Date("2019-12-31"), by = "day"))
df$counts <-sample(seq(from = 20, to = 50, by = 5), size = 365, replace = TRUE)


breaks_daily <- seq(from = min(df$date), to = max(df$date), by = "1 day")

labels_7_days <- format(seq(from = min(df$date), to = max(df$date), by = "7 days"), "%b-%d")
labels_final <- c(sapply(labels_7_days, function(x) {
  c(x, rep("", 6))
})) [1:length(breaks_daily)] #that is the crucial bit

ggplot(df, aes(y = counts, x = date)) +
  geom_col(fill = "#99CCFF", width=1) + 
  labs(x="Date", y="Quantity of Fruits") + 
  scale_x_date(labels = labels_final, breaks = breaks_daily, expand=c(0,0)) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Created on 2020-05-30 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions