R - How to get the time elapsed between two points? - r

I've tried to use Sys.time to get the time elapsed between two points. However, it doesn't output in a way I like.
This is how it looks now:
a <- Sys.time
...running stuff between these two points...
b <- Sys.time
c <- b - a
c
Time difference of 1.00558 hours
I only want the number and the units. I know that to get just the number I can do:
c[[1]]
However, sometimes the result of c can give me seconds or minutes. I only want instances wherein I have the number and when the units are in hours. Does anyone know of a way such that I would get something like the following, using Sys.time() (or any alternative):
if (units == "hours")
{
if (number => 1)
{
#do something
}
}

Using difftime of base R allows you to obtain the time difference in different units. Rest is formatting.
a = Sys.time()
Sys.sleep(5) #do something
b = Sys.time()
paste0(round(as.numeric(difftime(time1 = b, time2 = a, units = "secs")), 3), " Seconds")
#[1] "5.091 Seconds"

The package tictoc simplifies this kind of timing. It doesn't return hours, but we can create a new function that converts its second-based measurements into hours.
library(tictoc)
toc_hour <- function() {
x <- toc()
(x$toc - x$tic) / 3600
}
You normally start the timer with tic() and stop it with toc().
tic()
Sys.sleep(2)
toc()
# 2.02 sec elapsed
Calling toc_hour() instead of toc() returns the number of hours that have elapsed.
tic()
Sys.sleep(2)
toc_hour()
# 2.25 sec elapsed
# elapsed
# 0.000625
It still prints the number of seconds above the hours, but if you capture the result it will only store the number of hours for downstream analysis.
tic()
Sys.sleep(2)
x <- toc_hour()
if(x < 1) {print("This took under an hour")}

You can evaluate everything as an argument to the system.time function. It will give you the elapsed time in seconds.
paste0(system.time( rnorm(1000000, 0, 1) )[3] / 3600, " hours")
# "2.58333333334172e-05 hours"
Alternatively, you can use Frank's suggestion in the comments. difftime(b, a, units = "hours") which is probably the dominant solution in most cases

The tictoc package normally returns seconds. The other solutions from this package manually converts this to other units but I find it still doesn't look right. Instead, use the built-in func.toc argument in toc() to change the output. For example:
toc_min <- function(tic,toc,msg="") {
mins <- round((((toc-tic)/60)),2)
outmsg <- paste0(mins, " minutes elapsed")
}
And then:
tic()
Sys.sleep(1)
toc(func.toc=toc_min)
returns
0.02 minutes elapsed

I think lubridate is the quickest solution for you:
start <- Sys.time()
## Do Stuff here
end <- Sys.time()
elapsed <- lubridate::ymd_hms(end) - lubridate::ymd_hms(start)
message(elapsed)
It should return something useful like:
"Time difference of 12.1 hours"

Maybe you can try the ´tictoc´ package.
As described in the documentation you can do the following:
tic()
#Do something
toc(log = TRUE, quiet = TRUE)
#Put the result in a log
log.txt <- tic.log(format = TRUE)
#Extract only the value
res <- gsub( " sec elapsed", "", unlist(log.txt))
#Clear the log
tic.clearlog()
That way, res gives you only the value and is in seconds, so it is pretty simple to have hours then.
Moreover, if you don't clear the log you can put successions of tic() and toc() and put everything in your log.txt, and then gsub( " sec elapsed", "", unlist(log.txt)) will give you a vector of strings with the value in seconds for each iteration which can be pretty useful

Related

Is difference of Sys.time() a reliable execution time estimate in R?

For the code snippet
start <- Sys.time()
Sys.sleep(2)
end <- Sys.time()
print(paste('Time difference :', end-start))
No surprises in the output
[1] "Time difference : 2.01378774642944"
But for the below code snippet :
start <- Sys.time()
x <- matrix(rnorm(7500000), nrow=500, ncol=15000)
x <- cor(x)
end <- Sys.time()
print(paste('Time difference :', end-start))
I get the output as :
[1] "Time difference : 1.20198894341787"
However, the execution of this code snippet actually takes about 50 seconds on my laptop.
Why this difference ?
Is this not an ideal way to measure execution time ?
Here is the output I tried
First example - the calculation output is 2.2... and it's in second.
> start <- Sys.time()
> Sys.sleep(2)
> end <- Sys.time()
> print(paste('Time difference :', end-start))
[1] "Time difference : 2.20864367485046"
> difftime(end, start, units = "mins")
Time difference of 0.03681073 mins
Second example - the calculation output is 1.77... and it is in minutes
> start <- Sys.time()
> x <- matrix(rnorm(7500000), nrow=500, ncol=15000)
> x <- cor(x)
> end <- Sys.time()
> print(paste('Time difference :', end-start))
[1] "Time difference : 1.77510009209315"
> difftime(end, start, units = "mins")
Time difference of 1.7751 mins
You can see that the Time difference you output is actually in minutes but it doesn't state that is minutes or seconds so that it confusing. I recommend you use the difftime() function instead.

I want to print start time, end time and total execution in R, and append a label to it

old <- Sys.time()
// MY code
new <- Sys.time()
total time = old-new
the output comes "Time difference of -6.661923 secs"
instead i want "Execution time : 0.35secs"
You can use sprintf as below:
old <- Sys.time()
rnorm(500,0,1)
new <- Sys.time()
x <- (new - old)
sprintf("The execution time is %5.2f secs",x)
Output:
[1] "The execution time is 1.08 secs"
Something like
old <- Sys.time()
#code
new <- Sys.time()
total_time <- paste0("Execution time: ", as.numeric(new-old), "secs")

How do I run a function every second

I want to run a function that takes less than one second to execute. I want to run it in a loop every second. I do not want to wait one second between running the function like Sys.sleep would do.
while(TRUE){
# my function that takes less than a second to run
Sys.sleep(runif(1, min=0, max=.8))
# wait for the remaining time until the next execution...
# something here
}
I could record a starttime <- Sys.time() and do a comparison every iteration through the loop, something like this...
starttime <- Sys.time()
while(TRUE){
if(abs(as.numeric(Sys.time() - starttime) %% 1) < .001){
# my function that takes less than a second to run
Sys.sleep(runif(1, min=0, max=.8))
print(paste("it ran", Sys.time()))
}
}
But my function never seems to be executed.
I know python has a package to do this sort of thing. Does R also have one that I don't know about? Thanks.
You can keep track of the time with system.time
while(TRUE)
{
s = system.time(Sys.sleep(runif(1, min = 0, max = 0.8)))
Sys.sleep(1 - s[3]) #basically sleep for whatever is left of the second
}
You can also use proc.time directly (which system.time calls), which for some reasons got better results for me:
> system.time(
for(i in 1:10)
{
p1 = proc.time()
Sys.sleep(runif(1, min = 0, max = 0.8))
p2 = proc.time() - p1
Sys.sleep(1 - p2[3]) #basically sleep for whatever is left of the second
})
user system elapsed
0.00 0.00 10.02
Here are some alternatives. These do not block. That is you can still use the console to run other code while they are running.
1) tcltk Try after in the tcltk package:
library(tcltk)
run <- function () {
.id <<- tcl("after", 1000, run) # after 1000 ms execute run() again
cat(as.character(.id), "\n") # replace with your code
}
run()
Running this on a fresh R session gives:
after#0
after#1
after#2
after#3
after#4
after#5
after#6
after#7
...etc...
To stop it tcl("after", "cancel", .id) .
2) tcltk2 Another possibility is tclTaskSchedule in the tcltk2 package:
library(tcltk2)
test <- function() cat("Hello\n") # replace with your function
tclTaskSchedule(1000, test(), id = "test", redo = TRUE)
Stop it with:
tclTaskDelete("test")
or redo= can specify the number of times it should run.
Another non-blocking alternative worth mentioning is provided by library(later), via using later() recursive:
print_time = function(interval = 10) {
timestamp()
later::later(print_time, interval)
}
print_time()
The example is taken from here.
The shiny package has a function invalidateLater() which can be use to trigger functions. Have a look at http://shiny.rstudio.com/gallery/timer.html
Although its very late.
As an alternative we can use recursion. I don't know if its the solution you are looking for. But it executes function at regular interval.
ssc <- function(){
x <- rnorm(30,20,2)
print(hist(x))
Sys.sleep(4)
ssc()
}
ssc()

How to avoid toc() printing the time elapsed in Julia?

This might be a really stupid question, but I'll go ahead anyway. I'm trying to use Julia's tic() and toc() inside a loop in order to figure out some timing issues. A dummy example is shown below:
elapsedTime = zeros(3);
for i = 1:3
tic();
pause(i)
ElapsedTime[i] = toc();
end
The goal is to store the elapsed time intervals in the array ElapsedTime. The issue is that toc() seems to a) print the elapsed time to screen and b) store it as wanted.
Is there some simple trick to avoid a), ie. that toc() prints the result? It's not a huge problem, just annoying if the number of iterations is large.
Any help will be greatly appreciated!
there is another version of toc() called toq() which doesn't print a thing and returns the elapsed time.
You'll want the #elapsed macro.
elapsedTime = zeros(3);
for i = 1:3
elapsedTime[i] = #elapsed sleep(i)
end
I suppose you could take the time manually and store it in the array>
elapsedTime = zeros(3);
for i = 1:3
t1 = time_ns()
rand(10000000)
t2 = time_ns()
elapsedTime[i] = (t2 - t1)/1.0e9
end

format time span to show hours, minutes, seconds

I've been trying to find a simple way of formatting the output from difftime into HH:MM:SS.ms. So far I haven't come across anything which I was surprised by.
I did write the function below which almost does it. The limitation is the presentation of the numbers as significant single digits. eg 2hr, 3mins, 4.5secs becomes "2:3:4.5" instead of "02:03:04.5"
Does anyone have a better suggestion?
format.timediff <- function(start_time) {
diff = as.numeric(difftime(Sys.time(), start_time, units="mins"))
hr <- diff%/%60
min <- floor(diff - hr * 60)
sec <- round(diff%%1 * 60,digits=2)
return(paste(hr,min,sec,sep=':'))
}
In addition to #GSee's comment, you could use a function like this:
f <- function(start_time) {
start_time <- as.POSIXct(start_time)
dt <- difftime(Sys.time(), start_time, units="secs")
# Since you only want the H:M:S, we can ignore the date...
# but you have to be careful about time-zone issues
format(.POSIXct(dt,tz="GMT"), "%H:%M:%S")
}
f(Sys.Date())
Merge_Charge_Point$Duration<- difftime(Merge_Charge_Point$EndConnectionDateTime, Merge_Charge_Point$StartConnectionDateTime, units="secs")
This is the code. But this code transforms the data in to seconds but the outcome should be a time string.

Resources