6

I've got an xts df of the following format:

structure(c("May 2022", "Jun 2022", "Jul 2022", "Aug 2022", "Sep 2022", 
"Oct 2022", "Nov 2022", "Dec 2022", " 3035.199", " 5500.000", 
"11568.750", " 2510.000", " 6999.999", "21792.149", " 9750.000", 
" 5624.999", " 2250.000", " 4136.975", " 6525.500", " 2771.875", 
" 4637.500", "16273.499", " 6000.000", " 4494.649", " 2500.000", 
"    0.000", " 3029.000", " 2803.500", "    0.000", "14481.250", 
" 4374.998", " 4062.498", "    0.000", " 3075.000", " 6939.249", 
" 1500.000", " 4183.157", " 5769.000", " 3559.500", " 3250.000"
), class = c("xts", "zoo"), index = structure(c(1651363200, 1654041600, 
1656633600, 1659312000, 1661990400, 1664582400, 1667260800, 1669852800
), tzone = "UTC", tclass = "yearmon"), .Dim = c(8L, 5L), .Dimnames = list(
    NULL, c("Month", "Cat 1", "Cat 2", "Cat 3", "Cat 4")))

I'm trying to create a stacked bar chart using the dygraphs library.

library(dygraphs)
library(lubridate)
today <- as.Date(Sys.time())
    last_6 <- today+months(-6)
        dygraph(df) %>%
          dyAxis("y", label= "Total") %>%
          dyRangeSelector(dateWindow = c(last_6, today)) %>%
          dyMultiColumnGroup(c("Cat 1", "Cat 2", "Cat 3", "Cat 4"))

This produce a bar chart that looks like this:Current bar chart

I was wondering if anyone had any advice on how to make stacked bar chart? Many of the guides talk about bringing in plotters, but unfortunately they are not detailed enough for me to properly understand what is going on.

Adding this:

dyStackedBarGroup(c("Cat 1", "Cat 2", "Cat 3", "Cat 4"))

instead of the dyMultiColumnGroup line leads to a:

Error in cumulativeYval + points : non-numeric argument to binary operator
Zoe
  • 27,060
  • 21
  • 118
  • 148
alec22
  • 735
  • 2
  • 12
  • 1
    `object 'last_6' not found` error when running data and code in question. Do you get this when running the question in a fresh version of R? – Peter Dec 20 '22 at 16:18
  • 1
    Hi Peter, sorry for that, it should be corrected now (lubridate was needed) – alec22 Dec 20 '22 at 16:32

2 Answers2

4

It seems that you should create each time series as ts, so I convert them each separately and after that combined them with cbind. Here is a reproducible example:

Cat1 <- ts(c(3035.199, 5500.000, 11568.750, 2510.000, 6999.999, 21792.149, 9750.000, 5624.999), start = c(2022, 5), end = c(2022, 12), frequency = 12)
Cat2 <- ts(c(2250.000, 4136.975, 6525.500, 2771.875, 4637.500, 16273.499, 6000.000, 4494.649), start = c(2022, 5), end = c(2022, 12), frequency = 12)
Cat3 <- ts(c(2500.000, 0.000, 3029.000, 2803.500, 0.000, 14481.250, 4374.998, 4062.498), start = c(2022, 5), end = c(2022, 12), frequency = 12)
Cat4 <- ts(c(0.000, 3075.000, 6939.249, 1500.000, 4183.157, 5769.000, 3559.500, 3250.000), start = c(2022, 5), end = c(2022, 12), frequency = 12)

df <- cbind(Cat1, Cat2, Cat3, Cat4)

library(dygraphs)
library(lubridate)

today <- as.Date(Sys.time())
last_6 <- today+months(-6)
dygraph(df) %>%
  dyAxis("y", label= "Total") %>%
  dyRangeSelector(dateWindow = c(last_6, today)) %>%
  dyStackedBarGroup(name = c("Cat1", "Cat2", "Cat3", "Cat4"))

Created on 2022-12-22 with reprex v2.0.2

Quinten
  • 35,235
  • 5
  • 20
  • 53
4

While Quinten's got a great working answer, I thought I would add to it.

You don't need separate ts objects; you do need the data to be numeric, though.

Assuming the data from dput is named df:

# drop the months column, change data to numeric, restore ts class
df <- df[ ,-1] %>% sapply(as.numeric) %>%
  ts(start = c(2022, 5), deltat = 1/12)

Now you're ready to graph.

dygraph(df) %>%
  dyAxis("y", label= "Total") %>%
  dyRangeSelector(dateWindow = c(today() - months(6), today())) %>%
  dyStackedBarGroup(dimnames(df)[[2]])

enter image description here

Kat
  • 15,669
  • 3
  • 18
  • 51
  • Thanks for this I think it's almost fixed. Though, it seems the ts object breaks the order of the data (by month), any idea how to get around that? – alec22 Dec 22 '22 at 23:30
  • 1
    Oh man, I figured out what happened. When I first posted this answer, I set the plot range from May to December and realized that wasn't what you were looking for. When I changed the range selector, I changed the start date in the call for `ts()`. That shouldn't have happened. I've fixed the code now. The only change is in the argument `start` in the call for`ts()` – Kat Dec 23 '22 at 00:58