2

Following from this question: How can I calculate average hour of an event? where we wanted to compute the average circular mean and median, how would one calculate the difference between each time point and the mean? Would it be enough to subtract each data point from the mean? The code below doesn't work. The goal is to achieve something along the lines of - if there are two data points 22 and 1 and the circular mean is 23, then the first point is one hour early and the second is two hours past, so -1 and +2. But I don't know if this is the best way of computing time differences when considering the circular nature of clock time.

library(circular)

hours <- c(1, 20.10, 21, 22, 23 , 0, 1, 2.5)

hours.circ <- circular(hours, template = "clock24", units = "hours")

mean.circ <- mean(hours.circ)
as.numeric(mean.circ) %% 24
## [1] 0

median.circ <- median(hours.circ)
as.numeric(median.circ) %% 24
## [1] 0

plot(hours.circ)
points(mean.circ, col = "red", cex = 3)
points(median.circ, col = "blue", cex = 2)

for (i in hours.circ){
  
  x = as.numeric(hours.circ - mean.circ)%% 24
  print(x)
}
CatM
  • 284
  • 2
  • 12

1 Answers1

0

To achieve what you want to do, you can use the tidyverse's reframe function.

hours <- c(1, 20.10, 21, 22, 23 , 0, 1, 2.5)

hours.circ <- circular(hours, template = "clock24", units = "hours")

mean.circ <- mean(hours.circ)
as.numeric(mean.circ) %% 24
#> [1] 23.3358

median.circ <- median(hours.circ)
as.numeric(median.circ) %% 24
#> [1] 23.5

library(tidyverse)
library(lubridate)

hours_df <- data.frame(hours_start = hours) %>%
  mutate(hours_start = case_when(hours_start<12 ~ lubridate::ymd_hms("2023-06-26 00:00:00") + hours_start*60*60,
                                 hours_start>12 ~ lubridate::ymd_hms("2023-06-25 00:00:00") + hours_start*60*60)) %>%
  reframe(hours_start = hours_start,
          hours_mean = mean(hours_start),
          hours_diff = hours_start - mean(hours_start))

hours_df
#>           hours_start          hours_mean  hours_diff
#> 1 2023-06-26 01:00:00 2023-06-25 23:19:30  100.5 mins
#> 2 2023-06-25 20:06:00 2023-06-25 23:19:30 -193.5 mins
#> 3 2023-06-25 21:00:00 2023-06-25 23:19:30 -139.5 mins
#> 4 2023-06-25 22:00:00 2023-06-25 23:19:30  -79.5 mins
#> 5 2023-06-25 23:00:00 2023-06-25 23:19:30  -19.5 mins
#> 6 2023-06-26 00:00:00 2023-06-25 23:19:30   40.5 mins
#> 7 2023-06-26 01:00:00 2023-06-25 23:19:30  100.5 mins
#> 8 2023-06-26 02:30:00 2023-06-25 23:19:30  190.5 mins
U Bhalraam
  • 96
  • 7
  • 2
    The results are incorrect since they do not understand the circular nature of time, so there is not a difference of 22+ hours between the mean (23.3358) and 1AM. – CatM Jun 25 '23 at 20:28
  • Yes you are right. Apologies. I tried to figure out how to implement time's circular nature in your example without the use of datetime. But found this bit hard. So I have produced an example with datetime. Hope it helps. ( I have edited the above answer) – U Bhalraam Jun 25 '23 at 21:19
  • I only now noticed that the hours_mean is different from mean.circ, is this because of rounding? – CatM Jun 26 '23 at 21:09