0

I am running an analysis looking at the diel and seasonal activity patterns of bats. I'm hoping to plot time on the y-axis centered around midnight but am not sure how. Right now the y-axis runs 0-24 hours. I am using ggplot2. The code is below along with a picture of the plot.

library(ggplot2)
library(ggExtra) #for ggMarginal()

p <- ggplot(LBB, aes(x = RecordingDate, y = Time)) + 
          geom_point(size = .5) +  
          theme(legend.position="none")

p2 <- ggMarginal(p, type = "density")

plot

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Welcome! Could you please share your data using `dput()`? You are more likely to get a solution if others can reproduce your plot - see [here](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) for details on how to include data in your question – Jan Boyer Oct 18 '21 at 16:44

1 Answers1

0

I do not know of a way to center Time only data on midnight in a ggplot, but as a fairly simple workaround you can convert your times to datetimes, with all times before midnight coded as one day (you can choose any arbitrary day, in the code here I used today), and all times after midnight coded as the next day. You can then make a ggplot with a datetime axis centered on the midnight between those two days, and do some axis label formatting to make it look like a time only axis.

library(tidyverse)
library(hms) #package for handling time data

#Generate date and time data
LBB <- data.frame(RecordingDate = 
                    rep(seq.Date(as.Date("2021-04-01"), as.Date("2021-04-20"), 
                                 "days"), 25),
                  Time = hms(sample(0:59, replace = TRUE, 500),
                             sample(0:59, replace = TRUE, 500),
                             sample(c(0:5, 20:23), replace = TRUE, 500)))

# Make a graph.datetime column that assigns all times before midnight to the same
# date, and all times after midnight to the next day (you can choose any day)
LBB <- LBB %>%
  mutate(graphing.date = if_else(
    Time > parse_hms("12:00:00"), as.Date("2021-10-19"), #times 12 to 24 are this date
                     as.Date("2021-10-20")), #other times (0-12) are this date
#combine date and time to get a graphing datetime spread over two days
#(now you have data that is centered on midnight)
    graphing.datetime = as.POSIXct(paste(graphing.date, Time)))

#Graph, but use recording.datetime, not Time as y variable
p <- ggplot(LBB, aes(x = RecordingDate, y = graphing.datetime)) + 
  geom_point() +
  #format the y axis so it looks like Time even though it is datetime
  scale_y_datetime("Time", #change axis title back to time
                   #Set limits to show a full day
                   limits = c(as.POSIXct("2021-10-19 12:00:00"),
                              as.POSIXct("2021-10-20 12:00:00")),
                   expand = c(0,0), #turn off axis limit expansion
                   date_breaks = "4 hours", #set custom axis breaks
                   date_labels = "%H:%M") #Hours:minutes only for labels

p

enter image description here

Jan Boyer
  • 1,540
  • 2
  • 14
  • 22
  • Thank you so much! This seems to be working! Although I'm wondering what the following means......rep(seq.Date(as.Date("2021-04-01"), as.Date("2021-04-20"), "days"), 25), I'm hoping to have my dates between June and September. I will be making different plots for 2017, 18, 19, and 20 for that time range. When I try to adjust those dates to "2017-06-01 and 2017-09-01 I get the following error...Error in data.frame(RecordingDate=rep(seq.Date(as.Date("2017-07-01"), : arguments imply differing number of rows: 800, 500. Do you know what I am doing wrong? – elyse.mallinger Oct 19 '21 at 19:05
  • If I use the April dates that you use, I get the plot with points along those dates although I don't have any data from those dates – elyse.mallinger Oct 19 '21 at 19:15
  • Those lines just generate practice data with column names that match your data since I did not have your data. Since you already have your data in your R session, you should ignore the `#Generate date and time data` part of my code, and start running my code at `# Make a graph.datetime column...` – Jan Boyer Oct 19 '21 at 21:07
  • All of the axis are correct now, however, the time is showing up as "0" for all points. Any idea why? – elyse.mallinger Oct 19 '21 at 22:59
  • No idea without seeing your data/code, but my guess might be that there's a format issue with times (i.e. my code uses H:M:S times but maybe yours are just H:M?). Datetimes and times can cause errors if they aren't formatted the way a function expects. The first thing I would do is check the format of your times and datetimes and see if everything looks okay. – Jan Boyer Oct 20 '21 at 23:25