Reputation: 151
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
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