R timestamp difference printing - r

In below code, the last and the second last R codes produce a bit different result, why? After running the last line why don't I get output "time difference is Time difference of 5 mins"?
how could I get such output?
filenames <- c("CH7Data_20130401T130110.csv", "CH7Data_20130401T130610.csv")
timestamps <- gsub(".*_([^.]+).*", "\\1", filenames)
## [1] "20130401T130110" "20130401T130610"
timestamps <- as.POSIXlt(timestamps, format = "%Y%m%dT%H%M%S")
## [1] "2013-04-01 13:01:10 PDT" "2013-04-01 13:06:10 PDT"
timestamps[2]-timestamps[1]
##Time difference of 5 mins
cat("time difference is",timestamps[2]-timestamps[1])
##time difference is 5

'difftime'-objects are atomic objects with a special class so they have a print method that changes the output seen at the console. If you want as stated in the comment to print a redundant message that includes what comes to the console and some sort of preamble, then this would work:
> cat("time difference is",capture.output(timestamps[2]-timestamps[1]) )
time difference is Time difference of 5 mins
You could inset a line feed at the end of your preamble text:
> cat("time difference is\n",capture.output(timestamps[2]-timestamps[1]) )
time difference is
Time difference of 5 mins

Try
diff = timestamps[2]-timestamps[1]
cat("time difference is",diff,attr(diff,"units"),"\n")

Related

converting dates in R is changing to future dates, not past

I use this:
want=as.Date(date, '%d-%b-%y')
to convert dates like this: 1-JAN-52
Instead of returning '1952-01-01' I am getting '2052-01-01'. Any advice?
Welcome to modern computers, all shaped after the early Unix systems of the 1970s. The start of time, so to speak, is the epoch, aka 1 Jan 1970.
Your problem here, in a nutshell, is the inferior input data. You only supply two years and by a widely followed convention, values less than 70 are taken for the next century. It's all about the epoch.
So you have two choices. You could preprend '19' to the year part and parse via %Y, or you could just take the year value out of the date and reduce it by 100 if need be.
Some example code for the second (and IMHO better) option, makeing 1970 the cutoff date:
> datestr <- "1-Jan-52"
> d <- as.Date(datestr, '%d-%b-%y')
>
> d
[1] "2052-01-01"
>
> if (as.integer(strftime(d, "%Y")) >= 1970) {
+ dp <- as.POSIXlt(d)
+ dp$year <- dp$year - 100
+ d <- as.Date(dp)
+}
> d
[1] "1952-01-01"
>
You need to go via POSIXlt to get the components easily.

lubridate::duration("minutes") returns an error when duration less than 60 seconds

I am timing events that are usually of multiple minutes duration but occasionally an event will be less than 60 seconds and lubridate::duration() returns an erroneous value.
I can fix this problem with an IF and 2 duration functions by checking for time differences greater than or less than 60 seconds but it seems such an inelegant method.
library(lubridate)
for (x in c(59, 60)) {
startTime <- Sys.time()
Sys.sleep(x)
print(duration(as.numeric(Sys.time() - startTime), "minutes" ))
}
[1] "3543.86645793915s (~59.06 minutes)"
[1] "60.0540399551392s (~1 minutes)"
I just want time less than 60 seconds in decimal minutes or just seconds.
Thank you.
I am supposing your interval of time are objects of class difftime. If it is like that, see the next script:
#Create object difftime
a <- Sys.time()
b <- Sys.time()
DELTA_TIME <- b - a
#print the duration
print(duration(as.numeric(DELTA_TIME,units='mins'),units='minutes'))
See that this way of printing the duration will accept any object of class difftime. The important thing is the argument unit='mins' in the function as.numeric

Descriptive statistics of time variables

I want to compute simple descriptive statistics (mean, etc) of times when people go to bed. I ran into two problems. The original data comes from an Excel file in which just the time that people went to bed, were typed in - in 24 hrs format. My problem is that r so far doesn't recognizes if people went to bed at 1.00 am the next day. Meaning that a person who went to bed at 10 pm is 3 hrs apart from the one at 1.00 am (and not 21 hrs).
In my dataframe the variable in_bed is a POSIXct format so I thought to apply an if-function telling that if the time is before 12:00 than I want to add 24 hrs.
My function is:
Patr$in_bed <- if(Patr$in_bed <= ) {
Patr$in_bed + 24*60*60
}
My data frame looks like this
in_bed
1 1899-12-30 22:13:00
2 1899-12-30 23:44:00
3 1899-12-30 00:08:00
If I run my function my variable gets deleted and the following error message gets printed:
Warning message:
In if (Patr$in_bed < "1899-12-30 12:00") { :
the condition has length > 1 and only the first element will be used
What do I do wrong or does anyone has a better idea? And can I run commands such as mean on variables in POSIXct format and if not how do I do it?
When you compare Patr$in_bed (vector) and "1899-12-30 12:00" (single value), you get a logical vector. But the IF statement requires a single logical, thus it generates a warning and consider only the first element of the vector.
You can try :
Patr$in_bed <- Patr$in_bed + 24*60*60 * (Patr$in_bed < as.POSIXct("1899-12-30 12:00"))
Explanations : the comparison in the parenthesis will return a logical vector, which will be converted to integer (0 for FALSE and 1 for TRUE). Then the dates for which the statement is true will have +24*60*60, and the others dates will have +0.
But since the POSIXct format includes the date, I don't see the purpose of adding 24 hrs. For instance,
as.POSIXct("1899-12-31 01:00:00") - as.POSIXct("1899-12-30 22:00:00")
returns a time difference of 3 hours, not 21.
To answer your last question, yes you can compute the mean of a POSIXct vector, simply with :
mean(Patr$in_bed)
Hope it helps,
Jérémy

How to get milliseconds elapsed since midnight in R?

From the help of strptime and as.POSIXct, the POSIXlt and POSIXct classes seem only to record whole seconds.
(I need the milliseconds to pass them as a seed to a random number generator in a shared object.)
You can set the printed times to sub-second accuracy by changing the options:
options("digits.secs"=6)
The maximum is 6 digits - see options
Then you can get the system time to millisecond accuracy using:
as.POSIXlt(Sys.time())
That will print the time. To get the milliseconds since midnight that you're after simply use:
mySeed = as.POSIXlt(Sys.time())
mySeed = 1000*(mySeed$hour*3600 + mySeed$min*60 + mySeed$sec)
?Sys.time says:
On almost all systems it will have sub-second accuracy, possibly
microseconds or better. On Windows it increments in clock ticks
(usually 1/60 of a second) reported to millisecond accuracy.
So you can simply do this:
> foo <- Sys.time()
> foo
[1] "2014-05-22 12:40:55 CEST"
> hours <- as.POSIXlt(foo)$hour
> minutes <- as.POSIXlt(foo)$min
> seconds <- as.POSIXlt(foo)$sec
> hours*60*60*1000+minutes*60*1000+seconds*1000
[1] 45655771
In light of the help page, your results will depend on your system.
If you want to print the milliseconds, you can do this:
> options(digits.secs=3)
> foo
[1] "2014-05-22 12:40:55.771 CEST"

Milliseconds in POSIXct Class

How can I parse milliseconds correctly?
as.POSIXct function works as following in my environment.
> as.POSIXct("2014-02-24 11:30:00.001")
[1] "2014-02-24 11:30:00.000 JST"
> as.POSIXct("2014-02-24 11:30:00.0011")
[1] "2014-02-24 11:30:00.001 JST"
My R version is x86 v3.0.2 for Windows.
Specify the input format, using %OS to represent the seconds with their fractional parts.
x <- c("2014-02-24 11:30:00.123", "2014-02-24 11:30:00.456")
y <- as.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS")
When you come to display the value, append a number between 0 and 6 to the format string to tell R how many decimal places of seconds to display.
format(y, "%Y-%m-%d %H:%M:%OS6")
## [1] "2014-02-24 11:30:00.122999" "2014-02-24 11:30:00.456000"
(Note that you get rounding errors, and R's datetime formatting always rounds downwards, so if you show less decimal places it sometimes looks like you've lost a millisecond.)
Datetime formats are documented on the ?strptime help page. The relevant paragraph is:
Specific to R is '%OSn', which for output gives the seconds
truncated to '0 <= n <= 6' decimal places (and if '%OS' is not
followed by a digit, it uses the setting of
'getOption("digits.secs")', or if that is unset, 'n = 3').
Further, for 'strptime' '%OS' will input seconds including
fractional seconds. Note that '%S' ignores (and not rounds)
fractional parts on output.

Resources