Reputation: 343
I would like to plot midpoints of a day on a graph. I want "22:00" to be the first mark on the x-axis. Then 00:00, 02:00 up until 10:00.
It should look somewhat like the plots in this paper: https://www.ncbi.nlm.nih.gov/core/lw/2.0/html/tileshop_pmc/tileshop_pmc_inline.html?title=Click on image to zoom&p=PMC3&id=5479630_pone.0178782.g002.jpg
How can I do that? Example data and my graph down below.
DF <- data.frame(time_start = c("20:00", "21:00", "22:00", "23:00", "24:00", "21:30", "22:30", "20:00"),
time_end = c("01:00", "05:00", "06:00", "07:00", "08:00", "5:30", "6:30", "04:00"))
library(dplyr)
library(lubridate)
DF <- DF %>%
mutate_all(hm) %>%
mutate(time_end = time_end + (time_end < time_start) * days(1),
midpoint = seconds_to_period(as.numeric(time_start + time_end) / 2)) %>%
mutate_all(~sprintf("%02d:%02d", hour(.), minute(.)))
DF$midpoint <- strptime(DF$midpoint, "%H:%M", tz = "UTC")
DF$midpoint <- as.POSIXct(DF$midpoint)
What I have tried with limits:
lims <- as.POSIXct(strptime(c("2020-06-24 22:00","2020-06-24 10:00"), format = "%Y-%m-%d %H:%M"))
library(ggplot2)
ggplot(DF)+
geom_histogram(aes(x = midpoint, y = stat(width*density)), binwidth = 30*60)+
scale_x_datetime(date_breaks = "2 hour", date_labels = "%H:%M", limits = lims)
But it gives me only error messages.
Error in seq.int(0, to0 - from, by) : wrong sign in 'by' Additional: Error message :Removed 8 rows containing non-finite values (stat_bin).
Thanks in advance!
Upvotes: 1
Views: 948
Reputation: 50718
Judging from the paper figures you show, I think the sample data you give is poorly chosen for the task at hand, as you will need a date along with the time in order to achieve what you're trying to do.
So provided I understood your question correctly, this is what I would do.
First, let's create sample data
t0 <- as.POSIXct("2020-06-24 22:00", format = "%Y-%m-%d %H:%M")
df <- data.frame(
time_start = seq(t0, by = "hour", length.out = 10),
time_end = seq(t0 + 3 * 3600, by = "hour", length.out = 10))
We can then calculate mid points from the time durations defined by time_start
and time_end
.
# Calculate midpoints
df <- transform(df, time_midpoint = as.POSIXct(
(as.numeric(time_start) + as.numeric(time_end)) / 2,
origin = "1970-01-01"))
Finally we plot, and format the time axis according to your requirements:
library(ggplot2)
ggplot(df, aes(time_midpoint, y = 10)) +
geom_col() +
scale_x_datetime(
limits = c(min(df$time_start - 3600), max(df$time_end)),
breaks = scales::date_breaks("2 hour"),
date_labels = "%H:%M")
Or you can show the times as durations
ggplot(df, aes(t0, 1:10)) +
geom_linerange(aes(xmin = time_start, xmax = time_end)) +
scale_x_datetime(
name = "Times",
limits = c(min(df$time_start - 3600), max(df$time_end)),
breaks = scales::date_breaks("2 hour"),
date_labels = "%H:%M")
Upvotes: 1