rggplot2axis-labels

re-order factors on y axis of a gantt chart


I am trying to produce a Gantt chart with the locations on the y axis in alphabetical order but nothing I tried worked out. Here is the code:

gantt <- read_excel("2025-05-07_gantt_chart.xlsx")
gantt$row_id <- seq(1,nrow(gantt))
mgantt <- melt(gantt, measure.vars = c("start date", "end date"))
mgantt$yday <- yday(mgantt$value)
mgantt <- mgantt %>%
  arrange(as.factor(location))

ggplot(mgantt,
       aes(x = yday, 
           y = location,
           group = row_id)) +   
  geom_line(linewidth = 4) +
  facet_wrap(~year) +
  labs(title = NULL,
       x = "Julian date",
       y = NULL) +
  theme(panel.grid.minor = element_line(colour="white", linewidth = 0.5),
        legend.position="right",
        plot.title = element_text(hjust = 0.5))

And here is a subset of the data (hoping it works...)

structure(list(location = c("Hebron GBS", "Hibernia GBS", "SeaRose FPSO", 
"bdv", "Holyrood Thermal Generating station", "bdv", "Soldier's pond", 
"bdv", "bdv", "bdv"), year = c("2019", "2019", "2019", "2019", 
"2019", "2019", "2019", "2019", "2019", "2019"), `start date` = structure(c(1567296000, 
1567296000, 1567296000, 1569369600, 1569801600, 1569974400, 1569974400, 
1570233600, 1570406400, 1570665600), tzone = "UTC", class = c("POSIXct", 
"POSIXt")), `end date` = structure(c(1572480000, 1572480000, 
1572480000, 1569715200, 1572393600, 1570060800, 1572393600, 1570320000, 
1570492800, 1570752000), tzone = "UTC", class = c("POSIXct", 
"POSIXt")), ...5 = c("FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"only 1 day", "FALSE", "only 1 day", "only 1 day", "only 1 day"
)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
))

Thanks in advance!


Solution

  • The y axis is in alphabetical order, but factor ordering is such that earlier letters in the alphabet get the lowest values, so when these are plotted they are lower on the y axis. Therefore the order is alphabetical from bottom-to-top.

    You can use forcats::fct_rev from tidyverse to reverse this default ordering so that you can get alphabetical ordering from top-to-bottom.

    Incidentally, you are making this harder than you need to. Your data is already in the right format for a Gantt chart - just use geom_segment instead of geom_line

    library(tidyverse)
    
    gantt %>%
      mutate(location = fct_rev(location)) %>%
      ggplot(aes(`start date`, location)) +
      geom_segment(aes(xend = `end date`), linewidth = 2)  +
      theme_gray(16) +
      labs(y = NULL, x = "Julian Date")
    

    enter image description here