6

I'm new to the R statistics software and I roast coffee and record different events during the process. After the roasting process I would like to use R to do some calculation and analysis and derive important durations during the period by finding the time span between events - for example:

  • 00:00 Start
  • 05:10 Yellow
  • 07:15 Cinnamon
  • 09:00 First Crack
  • 11:30 End of roasting process

(if you are a coffee geek and want to know more about coffee roasting parameters: https://coffee-mind.com/profile/)

How/what format can I store these events and calculate the time span between events? I would like to show the time span in MM:SS but also see the total seconds in a MM:SS period. I have been looking at the different packages (like chron and lubridate) but they all seem to be concerned with time zone, absolute dates and so on and I'm only interested in minutes and seconds (regardless of day and time zone - not interesting at all here) and how to do calculations like simple subtractions on these recorded events. I'm not interested in 'how to write the code' but in functions (like chron and lubridate) that are already designed for this and how to use them directly (which I also assume is the most generally interesting approach for this community?)

Morten Münchow
  • 73
  • 1
  • 1
  • 6

3 Answers3

8

lubridate offers the functionality that you need. In addition to the POSIXct class, which does include date and time, it also offers the class period for durations. You can convert your times in %M:%S format to period as follows:

library(lubridate)
times <- c("00:00", "05:10", "07:15", "09:00", "11:30")
ms(times)
## [1] "0S"      "5M 10S"  "7M 15S"  "9M 0S"   "11M 30S"

You can then use as.period() to convert to the time unit you desire:

as.period(ms(times), unit = "sec")
## [1] "0S"   "310S" "435S" "540S" "690S"

If you convert to numeric now, you will get the seconds as numbers:

seconds <- as.numeric(as.period(ms(times), unit = "sec"))
seconds
## [1]   0 310 435 540 690

You can get now the difference in seconds between the events using diff() :

diff(seconds)
##[1] 310 125 105 150

Note that there are other variants of the function ms() for times in other formats: hm() (%H:%M:%S) and hms() (%H:%M).

Stibu
  • 15,166
  • 6
  • 57
  • 71
  • Great! I'll try it out :-) – Morten Münchow May 29 '16 at 19:07
  • I had the small issue that my times in coffee roasting are minutes and not hours, so I got some really big values when trying the above code. I found out that the hms function was the correct one to do for coffee roasting since it interprets 05:10 as 'five minutes and 10 seconds' where the hm function interpreted it as '5 hours and 10 minutes'. Thanks a lot for your text that solved my question completely with the hm -> hms as the only change I had to make to make it work for my purpose! If you are ever in Copenhagen you can take a roasting class for free :-) https://coffee-mind.com/shop – Morten Münchow May 29 '16 at 20:10
  • I'm sorry for this mistake. I was not careful enough when reading your question and simply assumed, you meant %H:%M. I am glad that you figured out yourself, how to adapt the solution, but I have still made some changes to the answer. Good luck with your coffee! – Stibu May 29 '16 at 20:27
  • Thanks Stibu! Much appreciated :-) – Morten Münchow May 30 '16 at 05:12
1

Well not sure if this helps but I made this function when I needed to convert time span of youtube videos to second. They are formatted hh:mm:ss so it could work for you when you input a vector with times like in your example

toseconds<-function(x){
  sec<-rep(NA,length(x))
  minu<-rep(NA,length(x))
  hodina<-rep(NA,length(x))
  total<-rep(NA,length(x))
  for (i in 1:length(x)) {
    if (str_count(x[i],":")==2) {
      sec[i]<-as.numeric(str_sub(str_replace(x[i],":",""),str_locate(str_replace(x[i],":",""),":")[ ,1]+1))
      minu[i]<-as.numeric(str_sub(x[i],str_locate(x[i],":")[ ,1]+1,str_locate(x[i],":")[ ,1]+2))
      hodina[i]<-as.numeric(str_sub(x[i],1,str_locate(x[i],":")[ ,1]-1))
    } else {
      sec[i]<-  as.numeric(str_sub(x[i],str_locate(x[i],":")[ ,1]+1))
      minu[i]<-as.numeric(str_sub(x[i],1,str_locate(x[i],":")[ ,1]-1))
      hodina[i]<-0
    }

    total[i]<-hodina[i]*3600+minu[i]*60+sec[i]
  } 

  total
}
Tomas H
  • 713
  • 4
  • 10
0

to avoid loading another library...

MinSeg=function(fim, ini){
  dif=as.numeric(difftime(fim, ini, units='min'))
  return(paste0(sprintf('%02d', as.integer(dif)), ":"
               ,sprintf('%02.0f', (dif-as.integer(dif))*60)))
}
ini=Sys.time()
fim=Sys.time()
MinSeg(fim,ini)
[1] "00:03"
xm1
  • 1,663
  • 1
  • 17
  • 28