Search code examples
rhighchartsr-highcharterstacked-bar-chart

R HighCharter Stacked Column Order & Colour


I am trying to change the order and colour of stacked bars in a highcharter plot in R.

I've been used to defining the factor levels when I come up against this issue in ggplot, and when searching for a solution in highcharter have found a few answers advising to similarly define the categories in hc_xAxis(), but this hasn't worked for me. Trying to do so plays havoc with my x-axis (no longer shows it as a date) and it still doesn't change the order. I have also had no joy in specifying the colours of the individual stacked bars, I'm used to doing this using scale_fill_manual() in ggplot, but here it looks like colours are being mapped alphabetically.

My goal is to get the stacked bar order as follows (from bottom to top): TL > WB > PB > UB > NACx > ACx.

Here's my dataframe:

df <- structure(list(Week = structure(c(19478, 19478, 19478, 19478, 
19478, 19478, 19478, 19485, 19485, 19485, 19485, 19485, 19485, 
19485, 19492, 19492, 19492, 19492, 19492, 19492, 19492, 19499, 
19499, 19499, 19499, 19499, 19499, 19499, 19506, 19506, 19506, 
19506, 19506, 19506, 19506, 19513, 19513, 19513, 19513, 19513, 
19513, 19513), class = "Date"), Status = c("ACx", "NACx", "PB", 
"Plan", "TL", "UB", "WB", "ACx", "NACx", "PB", "Plan", "TL", 
"UB", "WB", "ACx", "NACx", "PB", "Plan", "TL", "UB", "WB", "ACx", 
"NACx", "PB", "Plan", "TL", "UB", "WB", "ACx", "NACx", "PB", 
"Plan", "TL", "UB", "WB", "ACx", "NACx", "PB", "Plan", "TL", 
"UB", "WB"), Units = c(0, 7.13, 46.49, 298.03, 48.11, 20.25, 
166.12, 0, 12.87, 67, 298.03, 47, 38, 126.26, 0, 9, 66.27, 328.37, 
53.25, 90.25, 98.62, 0, 9.25, 53.13, 355.89, 53.11, 180.5, 45.13, 
4, 2.88, 0, 269.55, 6, 169.5, 0, 0, 0, 0, 355.89, 0, 0, 0)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -42L), groups = structure(list(
    Week = structure(c(19478, 19485, 19492, 19499, 19506, 19513
    ), class = "Date"), .rows = structure(list(1:7, 8:14, 15:21, 
        22:28, 29:35, 36:42), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -6L), .drop = TRUE))

... and the plot:

highchart() %>%
    hc_add_series(subset(df, Status == "Plan"), "column", grouping = FALSE, stack = "Plan", 
                  color = 'rgba(255, 255, 255, 0)', borderColor = "black",
                  hcaes(x = Week, y = round(Units, digits = 1), group = Status)) %>% 
    hc_add_series(subset(df, Status != "Plan"), type = 'column', grouping = FALSE, stack = "Activity", 
                  borderColor = "black", color = cols,
                  hcaes(y = Units, group=Status, x = Week)) %>% 
    hc_chart(plotBackgroundColor = "#F5F5F5") %>% 
    hc_plotOptions(series = list(stacking = "normal")) %>% 
    hc_xAxis(dateTimeLabelFormats = list(week = '%d-%b'), type = "datetime", 
             title = list(text = "Week Commencing"), gridLineWidth = 1, tickInterval = 604800000) %>% 
    hc_yAxis(title = list(text = "Activity)"))

cols <- c("ACx" = "#311432",
             "NACx" = "#a1045a",
             "WB" = "forestgreen",
             "TL" = "#D3D3D3",
             "PB" = "goldenrod",
             "UB" = "#bc544b")

Really appreciate any help.


Solution

  • One option would be to convert Status to a factor with the levels set in your desired order. Afterwards you could reorder your colors according to this order as well.

    library(highcharter)
    
    levels <- c("TL","WB", "PB", "UB", "NACx", "ACx", "Plan")
    df$Status <- factor(df$Status, rev(levels))
    
    cols <- cols[levels(df$Status)]
    cols <- cols[!is.na(names(cols))]
    
    highchart() %>%
      hc_add_series(subset(df, Status == "Plan"), "column",
        grouping = FALSE, stack = "Plan",
        color = "rgba(255, 255, 255, 0)", borderColor = "black",
        hcaes(x = Week, y = round(Units, digits = 1), group = Status)
      ) %>%
      hc_add_series(subset(df, Status != "Plan"),
        type = "column", grouping = FALSE, stack = "Activity",
        borderColor = "black", color = cols,
        hcaes(y = Units, group = Status, x = Week)
      ) %>%
      hc_chart(plotBackgroundColor = "#F5F5F5") %>%
      hc_plotOptions(series = list(stacking = "normal")) %>%
      hc_xAxis(
        dateTimeLabelFormats = list(week = "%d-%b"), type = "datetime",
        title = list(text = "Week Commencing"), gridLineWidth = 1, tickInterval = 604800000
      ) %>%
      hc_yAxis(title = list(text = "Activity)"))
    

    enter image description here