Home > OS >  R. ggplot Stacked histogram, Time series, combine two hour plots
R. ggplot Stacked histogram, Time series, combine two hour plots

Time:10-12

I have a stacked histogram, it looks like this: Time of day against count. Stacked by Depth

I have two issues:

  1. I want 24 columns, not 25 - so I need to combine the first and last somehow. st_time is time stripped from a datetime column over 6 months, output is POSIXct 2021-10-11 00:00:00 through 2021-10-11 23:59:54
All_M_dives$st_time <- format(as.POSIXct(All_M_dives$begdesc, format = "%d/%m/%Y %H:%M:%S"), format = "%H:%M:%S")
All_M_dives$st_time <- as.POSIXct(All_M_dives$st_time, format = "%H:%M:%S")
  1. I want to order the stack manually by depth 0,25,50,100,200. R does this alphabetically so you can see the incorrect order in the legend / on the graph.

I guess there might be a solution to just use alphabetical dbins and just to rename the legend if that's a possibility, I just thought of that.

gg <- ggplot(data = All_M_dives, aes(x = st_time, fill = dbins))   
  geom_histogram(colour = "black", position = "stack", binwidth = 3600 )  
  scale_x_datetime(date_labels = "%H:%M")  
  labs(title = NULL, x = "Time of Day", y = "Dive Count")  
  theme(legend.position = "none")  
  theme_classic()   theme(axis.text.x = element_text(angle=45)) 
gg

dput can be seen here: final version

CodePudding user response:

I think this can be solved most simply by adding center = 1800 to your geom_histogram line. This will make it so that each bin is 3600 seconds wide and spans the whole hour centered around second 1800.

fake <- data.frame(st_time = as.POSIXct("2021-10-12", tz = "GMT")   runif(1E5, max = 24*60*60),
                   dbins = sample(LETTERS[1:5], 1E5, replace = TRUE, prob = c(20, 2, 1, 5, 5)))

ggplot(data = fake, aes(x = st_time, fill = dbins))   
  geom_histogram(colour = "black", position = "stack", binwidth = 3600, center = 1800 )  
  scale_x_datetime(date_labels = "%H:%M")  
  labs(title = NULL, x = "Time of Day", y = "Dive Count")  
  theme(legend.position = "none")  
  theme_classic()   theme(axis.text.x = element_text(angle=45)) 

enter image description here

You could alternately do the binning yourself and feed that into ggplot to use geom_col, for an identical plot:

library(dplyr); library(lubridate)
fake %>%
  count(st_time = floor_date(st_time, "hour"), dbins) %>%
ggplot(aes(x = st_time   1800, y = n, fill = dbins))   
  geom_col(colour = "black", position = "stack", width = 3600)  
  scale_x_datetime(date_labels = "%H:%M")  
  labs(title = NULL, x = "Time of Day", y = "Dive Count")  
  theme(legend.position = "none")  
  theme_classic()   theme(axis.text.x = element_text(angle=45)) 

To change the series order, I suggest converting the dbins variable into an ordered factor. Adding this line changes the sorting and plotting order into the order I supply:

fake$dbins = factor(fake$dbins, levels = c("D", "A", "E", "B", "C"))

enter image description here

  • Related