1

I have a data.frame of the last 4 weeks and the first 4 weeks of 2022 and 2023. I'm looking to create a bar plot where my x-axis displays the last weeks of 2022 and then the first weeks of 2023. However, ggplot automatically sorts the week numbers ascending. I'm looking to instruct the computer to plot week 49,50,51,52 first and 1,2,3,4 second. Below a set of dummy data to explain the issue I am dealing with.

df.demo <- data.frame(year = c(2022,2022,2022,2022,2023,2023,2023,2023), week = as.integer(49,50,51,52,1,2,3,4), y = c(10,11,12,13,20,21,22,23))

ggplot(df.demo, aes(x=week, y=y))+ geom_col()

Produces this plot:

enter image description here

I know I can remove all other weeks by plotting 'week' as a factor but that still does not solve my arrangement issue.

A similar question was answered regarding the arranging of variables for plotting an x axis.

I'm avoiding a manual workaround and want to see if anyone has a more pragmatic solution. I tried browsing through Lubridate functions but I am only able to get the display I want if I plot the actual dates. Will not work with ISO week numbers. I'm thinking I can ask ggplot to grab the year AND week number for the display whilst only physically displaing the week number? In our industry, we talk and measure outputs by the week number and this is why I'd prefer to keep this display.

Martin Gal
  • 16,640
  • 5
  • 21
  • 39
Sergio Escalante
  • 219
  • 1
  • 2
  • 6

2 Answers2

1

You could add a reordered factor, reordering by year

df.demo %>% 
    mutate(order = fct_reorder(as.factor(week), year)) %>% 
    ggplot(aes(x=order, y=y))+ 
    geom_col()

enter image description here

Jonni
  • 804
  • 5
  • 16
1

one approach:

library(ggplot2)
library(lubridate)

df.demo <- 
  df.demo |>
  mutate(year = as_date(paste0(year,"-01-01")),
         xpos = year + as.duration(paste(week, 'weeks'))
         )

df.demo |>
  ggplot(aes(xpos, y, week)) +
  geom_col(aes(xpos, y)) +
  scale_x_date(breaks = df.demo$xpos, date_labels = '%W / %y') +
  labs(x = 'week')

bars by week-of-year

Haven't yet found out, why I have to supply df.demo$xpos instead of only xpos for the scale_x_date(breaks = ...). Any suggestions?

I_O
  • 4,983
  • 2
  • 2
  • 15