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
Related
I am trying to learn how to implement control structures such as FOR and while loops.
I created a function the simulates betting in a famous Brazilian lotto.
In the lotto, a player bets on 6 unique integers from a 1:60 vector (called your_bet).
The function samples 6 values from the 1 to 60 universe ("result") and tests how many values in result match your_bet, printing out:
your_bet
result
total points (out of 6 possible)
one of three possible commentaries on the result of the bet.
Code as follows:
```
LOTTO<-function(your_bet=sample(1:60, size=6, replace=FALSE)){
result<-sample(1:60, size=6, replace=FALSE)
logical_vector<-(your_bet %in% result)
total_points<-sum(as.integer(logical_vector))
print(paste(c("Your bet:", as.character(your_bet))), collapse="")
print(paste(c("Result", as.character(result))), collapse="")
print(paste(c("Total points", as.character(total_points))), collapse="")
if (total_points==6)
print("You are a millonaire")
else if (total_points==5)
print("5 points, you are rich!")
else print("good luck next time")
}
```
I then tried to implement a loop that would make the function go over and over again in a loop until total points>= a given target (here as target_points), modifying the function as bellow.
```
LOTTO<-function(your_bet=sample(1:60, size=6, replace=FALSE), stubborn_until_x_points=FALSE,
target_points)#inserted stubborn_until_x_points and target_points arguments{
result<-sample(1:60, size=6, replace=FALSE)
logical_vector<-(your_bet %in% result)
total_points<-sum(as.integer(logical_vector))
print(paste(c("Your bet:", as.character(your_bet))), collapse="")
print(paste(c("Result", as.character(result))), collapse="")
print(paste(c("Total points", as.character(total_points))), collapse="")
if (total_points==6)
print("You are a millonaire")
else if (total_points==5)
print("5 points, you are rich!")
else print("good luck next time")
if (stubborn_until_x_points==TRUE)#Inserted WHILE loop here{
while(total_points < target_points){
LOTTO(your_bet, stubborn_until_x_points=TRUE, target_points)}
}
}
```
This did make the function repeat in a loop, but for some reason, it keeps looping even when the condition is met.
Observation - I realized that when the condition is met on the first run, it actually stops, but after entering a loop, it goes on forever.
I can´t find what is wrong. Any ideas?
Thanks in advance.
I haven't dug quite deep into the function, but the only reason that this should not break at any point is when target_points > n_samples (6 here).
The problem in this case is quite obvious and simple to fix. Reduce target_points to be less than 6 or add n_samples (6 atm.) and make it greater than target_points. Rather than this I suspect the main problem lies within the recursive function though. R is rather restrictive when it comes to recursion, if one tries to do a simple recursion for example
i <- 0
f <- function(){
i <<- i + 1
f()
}
f()
i
# 896 on my pc
one can see that we cannot use recursion for very deep recursive functions (in R). This throws the very unhelpful error
Error: C stack usage 7974196 is too close to the limit
To alleviate this, one simply has to remove the recursion (simply in italian because sometimes it is not simple). In this case we just move the while loop to contain the main body of the function, and use an if statement to break early if necessary.
Below is a slightly modified version of the function (note that sample_n and number_range has been added as arguments).
In this function the while loop has been moved to contain the main body, and the result is instead printed at the end (using the variable res to figure out the result). At the end of the loop I use a if(isFALSE(stubborn_until_x_points))break statement to exit early if necessary.
LOTTO <- function(your_bet,
sample_n = 6,
number_range = 1:60,
stubborn_until_x_points = FALSE,
target_points){
if(missing(target_points) || target_points > sample_n)
stop('missing target_points or target_points too large')
total_points <- -Inf # Always smaller than target_points
i <- 0
res <- 0
# If you want a new bet every iteration.
# Add this at the end of the loop, but remove the 'if'
if(missing(your_bet))
your_bet <- sample(number_range, size=sample_n, replace=FALSE)
while(total_points < target_points){
result <- sample(number_range, size=sample_n, replace=FALSE)
logical_vector <- your_bet %in% result
total_points <- sum(logical_vector)
if (total_points==6){
res <- 1
}else if (total_points==5){
res <- 2
}
i <- i + 1
if(isFALSE(stubborn_until_x_points))
break
}
if(res == 1)
cat(res <- 'You\'re a millionaire!\n', sep = '\n')
else if(res == 2)
cat(res <- '5 points, you are rich!\n', sep = '\n')
else
cat(res <- 'Better luck next time.', sep = '\n')
c(result = res, number_of_tries = i)
}
The function is called as before, but now also returns the number of attempts and the result obtained from trials as shown below.
LOTTO(target_points = 6, stubborn_until_x_points = TRUE)
You're a millionaire!
#Output:
result number_of_tries
"You're a millionaire!\n" "8297820"
Removing recursion, including the body of the function inside the while loop, assigning -Inf to the initial total_points and adding the break statement were much usefull.
Addapting the answer by #Oliver yielded exactly what I was looking for:
LOTTO<-function(your_bet=sample(1:60, size=6, replace=FALSE), stubborn_until_x_points=FALSE,
target_points=0){
total_points<--Inf
while(total_points < target_points){
result<-sample(1:60, size=6, replace=FALSE)
logical_vector<-(your_bet %in% result)
total_points<-sum(as.integer(logical_vector))
print(paste(c("Your bet:", as.character(your_bet))), collapse="")
print(paste(c("Result", as.character(result))), collapse="")
print(paste(c("Total points", as.character(total_points))), collapse="")
if (total_points==6)
print("You are a millonaire")
else if (total_points==5)
print("5 points, you are rich!")
else print("good luck next time")
if (isFALSE(stubborn_until_x_points==TRUE))
break
}
His answer, however, yields interesting additional results, and better control over inadequate argument inputs
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
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()
I'm trying to get a function to run for a specified amount of time, at the moment I'm trying to use the system.time function. I can't figure out how to define a new variable that takes on cumulative value the function running, then put it into a while loop.
timer<-(system.time(simulated_results<-replicate(n=1,simulation(J,10000,FALSE,0.1),simplify="vector"))[3])
print(timer)
while(cumsum(timer)<15){
print(cumsum(timer))
simulated_results<-replicate(n=10000,simulation(J,10000,FALSE,0.1),simplify="vector")
}
I would greatly appreciate any help!!!
If you want to run some code for a specified number of seconds, you can try the following :
start <- as.numeric(Sys.time())
duration <- 5
results <- NULL
while(as.numeric(Sys.time())-start < duration) {
results <- c(results, replicate(...))
}
Of course, you have to change the value of duration (in seconds), and replace replicate(...) with your code.
You can use tryCatch approach for this task. For example, consider the following code
fun_test = function(test_parameter){
result <- 1+test_parameter #some execution
return(result)
}
time = 10 #seconds
res <- NULL
tryCatch({
res <- withTimeout({
check = fun_test(tsp)
}, timeout = time)
}, TimeoutException = function(ex) {
message("Timeout. Skipping.")
})
This program will run the function fun_test for 10 seconds. If the execution is successful in this time, the result is returned, else program is stoped. For more guidance, you can follow this URL
Time out an R command via something like try()
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.