R: Execute commands at exact time after program start - r

I am maybe misusing R a little, but I wish to execute R commands et specific times after my script started. The time when the commands should be executed is saved in a data frame.
e.g.
Time <- c(0.5, 5, 13, 30)
Text <- c("Half a second", "5 seconds", "13 seconds", "Half a minute")
df <- data.frame(Time = Time, Text = Text)
df
# Time Text
#1 0.5 Half a second
#2 5.0 5 seconds
#3 13.0 13 seconds
#4 30.0 Half a minute
The aim is to execute a command eg. print() after x Millisecond (stored in df$Time_ms) since the program start has past.
My first approach would be just to use Sys.sleep() between the commands. This would be almost acceptable, but since each command also takes some time (print() not really but others more) it will not be super accurate.
My best solution is to use 'while' loops:
# Programm start
start_time <- Sys.time() # Save Program start time.
for(i in 1:nrow(df)){
while(Sys.time() < df$Time[i] + start_time){} # Wait until the System Time is larger than start time plus the time when the command shall be executed.
print(paste(df$Text[i], "has passed.")) # Execute the command.
}
It is working. But I am not that experienced with programming, but I guess it is not a very elegant solution. What do you think? Does someone have a "nicer" solution?

I ended up using the proposal from nicola, with a minor change. If the program runs already for more than a minute and you subtract the 'start_time' current time 'Sys.time()' the result will be in minutes and not in second anymore. To prevent this, I use 'difftime'.
# Create example data.frame
Time <- c(0.5, 5, 13, 30)
Text <- c("Half a second", "5 seconds", "13 seconds", "Half a minute")
df <- data.frame(Time = Time, Text = Text)
# Programm start
start_time <- Sys.time() # Save Program start time.
for(i in 1:nrow(df)){
wait <- df$Time[i]-(as.numeric(difftime(Sys.time(),start_time, units = "secs"))) # Calculate the waiting time in second.
Sys.sleep(wait)
print(paste(df$Text[i], "has passed.")) # Execute the command.
}

Related

Adding time in milliseconds to Time Stamp in R

I am having an issue with adding time in ms to a specific time stamp. My data contain two variables, Start Time (Time, in HH:MM:SS.ss format) and time for a specific event given in ms that have passed since the Start Time (STime, numeric variables, i.e. 640654 ms, which equals 640.654 s or 10.678.. min). For example:
Time <- c("16:44:38.00", "16:44:38.00", "16:44:38.00")
STime <- c(640657, 940640, 955301)
Here on the forum I found the code (thank you #tstev) that should allow calculating FTime - Start Time with STime added, and shown in HH:MM:SS.ss format:
FTime <- strftime(strptime(Time,format="%H:%M:%OS")+(STime %% 1)+0.005,format="%H:%M:%OS3")
However, in my case it does not add STime properly - I've tried to present STime in seconds instead of ms (640.657, 940.640, 955.301) and then add - it still does not provide accurate results, here's what I've got:
"16:44:38.662", "16:44:38.645", "16:44:39.306"
Does anyone know how to fix this?
Cheers
You can use the library hms. I divided the microseconds by 1000 to render them as seconds, then converted the values.
library(hms)
library(tidyverse)
Time <- c("16:44:38.00", "16:44:38.00", "16:44:38.00") %>% as_hms()
STime <- (c(640657, 940640, 955301) / 1000) %>% hms(seconds = .)
(Time + STime) %>% as_hms()
# 16:55:18.657
# 17:00:18.640
# 17:00:33.301
Let me know if you have any questions.

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

R - Sys.time() and as.POSIXct() issue [duplicate]

I want to run a R code at a specific time that I need.
And after the process finished, I want to terminate the R session.
If a code is as below,
tm<-Sys.time()
write.table(tm,file='OUT.TXT', sep='\t');
quit(save = "no")
What should I do to run this code at "2012-04-18 17:25:40".
I need your help. Thanks in advance.
It is easiest to use the Task Scheduler of Windows, or a cron job under Linux. There you can specify a command or program that should be run at a certain time you specify.
If somehow you cannot use the cron job service and have to schedule within R, the following R code shows how to wait a specific amount of time so as to execute at a pre-specified target time.
stop.date.time.1 <- as.POSIXct("2012-12-20 13:45:00 EST") # time of last afternoon execution.
stop.date.time.2 <- as.POSIXct("2012-12-20 7:45:00 EST") # time of last morning execution.
NOW <- Sys.time() # the current time
lapse.time <- 24 * 60 * 60 # A day's worth of time in Seconds
all.exec.times.1 <- seq(stop.date.time.1, NOW, -lapse.time) # all of afternoon execution times.
all.exec.times.2 <- seq(stop.date.time.2, NOW, -lapse.time) # all of morning execution times.
all.exec.times <- sort(c(all.exec.times.1, all.exec.times.2)) # combine all times and sort from recent to future
cat("To execute your code at the following times:\n"); print(all.exec.times)
for (i in seq(length(all.exec.times))) { # for each target time in the sequence
## How long do I have to wait for the next execution from Now.
wait.time <- difftime(Sys.time(), all.exec.times[i], units="secs") # calc difference in seconds.
cat("Waiting for", wait.time, "seconds before next execution\n")
if (wait.time > 0) {
Sys.sleep(wait.time) # Wait from Now until the target time arrives (for "wait.time" seconds)
{
## Put your execution code or function call here
}
}
}

Simulate coin toss for one week?

This is not homework. I am interested in setting up a simulation of a coin toss in R. I would like to run the simulation for a week. Is there a function in R that will allow me to start and stop the simulation over a time period such as a week? If all goes well, I may want to increase the length of the simulation period.
For example:
x <- rbinom(10, 1, 1/2)
So to clarify, instead of 10 in the code above, how do I keep the simulation going for a week (number of trials in a week versus set number of trials)? Thanks.
Here is code that will continue to run for three seconds, then stop and print the totals.
x <- Sys.time()
duration <- 3 # number of seconds
heads <- 0
tails <- 0
while(Sys.time() <= x + duration){
s <- sample(0:1, 1)
if(s == 1) heads <- heads+1 else tails <- tails+1
cat(sample(0:1, 1))
}
cat("heads: ", heads)
cat("tails: ", tails)
The results:
001100111000011010000010110111111001011110100110001101101010 ...
heads: 12713
tails: 12836
Note of warning:
At the speed of my machine, I bet that you get a floating point error long before the end of the week. In other words, you may get to the maximum value your machine allows you to store as an integer, double, float or whatever you are using, and then your code will crash.
So you may have to build in some error checking or rollover mechanism to protect you from this.
For an accelerated illustration of what will happen, try the following:
x <- 1e300
while(is.finite(x)){
x <- x+x
cat(x, "\n")
}
R deals with the floating point overload gracefully, and returns Inf.
So, whatever data you had in the simulation is now lost. It's not possible to analyse infinity to any sensible degree.
Keep this in mind when you design your simulation.
While now is smaller than a week later time stamp append to x rbinmo(1,1,1/2)
R> week_later <- strptime("2012-06-22 16:45:00", "%Y-%m-%d %H:%M:%S")
R> x <- rbinom(1, 1, 1/2) // init x
R> while(as.numeric(Sys.time()) < as.numeric(week_later)){
R> x <- append(x, rbinom(1, 1, 1/2))
R> }
You may be interested in the fairly new package harvestr by Andrew Redd. It splits a task into pieces (the idea being that pieces could be run in parallel). The part of the package that applies to your question is that it caches results of the pieces that have already been processed, so that if the task is interupted and restarted then those pieces that have finished will not be rerun, but it will pick up on those that did not complete (pieces that were interupted part way through will start from the beginning of that piece).
This may let you start and stop the simulation as you request.

I want to run a R code at a specific time

I want to run a R code at a specific time that I need.
And after the process finished, I want to terminate the R session.
If a code is as below,
tm<-Sys.time()
write.table(tm,file='OUT.TXT', sep='\t');
quit(save = "no")
What should I do to run this code at "2012-04-18 17:25:40".
I need your help. Thanks in advance.
It is easiest to use the Task Scheduler of Windows, or a cron job under Linux. There you can specify a command or program that should be run at a certain time you specify.
If somehow you cannot use the cron job service and have to schedule within R, the following R code shows how to wait a specific amount of time so as to execute at a pre-specified target time.
stop.date.time.1 <- as.POSIXct("2012-12-20 13:45:00 EST") # time of last afternoon execution.
stop.date.time.2 <- as.POSIXct("2012-12-20 7:45:00 EST") # time of last morning execution.
NOW <- Sys.time() # the current time
lapse.time <- 24 * 60 * 60 # A day's worth of time in Seconds
all.exec.times.1 <- seq(stop.date.time.1, NOW, -lapse.time) # all of afternoon execution times.
all.exec.times.2 <- seq(stop.date.time.2, NOW, -lapse.time) # all of morning execution times.
all.exec.times <- sort(c(all.exec.times.1, all.exec.times.2)) # combine all times and sort from recent to future
cat("To execute your code at the following times:\n"); print(all.exec.times)
for (i in seq(length(all.exec.times))) { # for each target time in the sequence
## How long do I have to wait for the next execution from Now.
wait.time <- difftime(Sys.time(), all.exec.times[i], units="secs") # calc difference in seconds.
cat("Waiting for", wait.time, "seconds before next execution\n")
if (wait.time > 0) {
Sys.sleep(wait.time) # Wait from Now until the target time arrives (for "wait.time" seconds)
{
## Put your execution code or function call here
}
}
}

Resources