I have the sample code below:
f <- function(x) {
v = 0
start = Sys.time()
for (i in 1:x) {
v = v + 1
}
end = Sys.time()
print(end-start)
print(paste0("f() took: ", end-start))
}
f(10)
The 2 outputs are:
Time difference of 5.960464e-06 secs
"f() took: 5.96046447753906e-06"
My question is why when used with paste0 the output is different.
Edit:
If one wish to get the units of time do the following:
print(paste0("f() took: ", end-start, " ", units(end-start)))
Have a look at ?print.difftime:
The print() method calls these “time differences”.
It's an in-built method for print that displays differences in dates in this format.
class(Sys.Date()-Sys.Date()+1)
[1] "difftime"
class(paste(Sys.Date()-Sys.Date()+1))
[1] "character"
paste0("f() took: ", end-start) becomes a character class and so print will handle it differently
Related
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 create a program in R that takes integer user input and then adds it to the previous user input. ex. user input(say one day): 10, then (maybe the next day) user input: 15 --> output 25.Ideally this would accept nearly an infinite amount of input. here is what I have so far:
amount_spent <- function(){
i <-1
while(i<10){
n <- readline(prompt="How much did you spend?: ")
i<-i+1
}
print(c(as.integer(n)))
}
amount_spent()
Problems I have with this code are that it only saves the last input value, and it is difficult to control when User is allowed to input. Is there any way to save user input to a data that can be manipulated through readline()?
# 1.R
fname <- "s.data"
if (file.exists(fname)) {
load(fname)
}
if (!exists("s")) {
s <- 0
}
n <- 0
while (TRUE) {
cat ("Enter a number: ")
n <- scan("stdin", double(), n=1, quiet = TRUE)
if (length(n) != 1) {
print("exiting")
break
}
s <- s + as.numeric(n)
cat("Sum=", s, "\n")
save(list=c("s"), file=fname)
}
You should run the script like this: Rscript 1.R
To exit the loop press Ctrl-D in Unix, or Ctrl-Z in Windows.
An R-ish way to do it would be through closures. Here is an example for interactive use (i.e. within an R session).
balance_setup <- function() {
balance <- 0
change_balance <- function () {
n <- readline(prompt = "How much did you spend?: ")
n <- as.numeric(n)
if (!is.na(n))
balance <<- balance + n
balance
}
print_balance <- function() {
balance
}
list(change_balance = change_balance,
print_balance = print_balance)
}
funs <- balance_setup()
change_balance <- funs$change_balance
print_balance <- funs$print_balance
Calling balance_setup creates a variable balanceand two functions that can access it: one for changing the balance, one for printing it. In R, functions can only return a single value, so I bundle both functions together as a list.
change_balance()
## How much did you spend? 5
## [1] 5
change_balance()
## How much did you spend? 5
## [1] 10
print_balance()
## [1] 10
If you want many inputs, use a loop:
repeat{
change_balance()
}
Break the loop with Ctrl-C, Escape or whatever is used on your platform.
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
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")
In the following example I created the add_timing function operator. The input is a function (say mean) and it returns a function that does the same as mean, but reports on how long it took for the function to complete. See the following example:
library(pryr)
add_timing = function(input_function, specific_info) {
if (missing(specific_info)) specific_info = function(l) 'That'
function(...) {
relevant_value = specific_info(list(...))
start_time = Sys.time()
res = input_function(...)
cat(sprintf('%s took', relevant_value), difftime(Sys.time(), start_time, units = 'secs'), 'sec', '\n')
res
}
}
timed_mean = add_timing(mean)
# > timed_mean(runif(10000000))
# That took 0.4284899 sec
# [1] 0.4999762
Next I tried to use pryr::compose to create the same timed_mean function (I like the syntax):
timed_mean_composed = pryr::compose(add_timing, mean)
But this does get me the required output:
# > timed_mean_composed(runif(100))
# function(...) {
# relevant_value = specific_info(list(...))
# start_time = Sys.time()
# res = input_function(...)
# cat(sprintf('%s took', relevant_value), difftime(Sys.time(), start_time, units = 'secs'), 'sec', '\n')
# res
# }
It seems that the compose operation does not lead to the add_timing function actually being executed. Only after calling the function, the new timed_mean_compose actually shows the correct function output.
Based on the following example from Advanced R by #HadleyWickham I expected this to work as I used it (see below for an excerpt):
dot_every <- function(n, f) {
i <- 1
function(...) {
if (i %% n == 0) cat(".")
i <<- i + 1
f(...)
}
}
download <- pryr::compose(
partial(dot_every, 10),
memoise,
partial(delay_by, 1),
download_file
)
Where the dot_every function operator is used in the same way I use add_timing above.
What am I missing?
The difference is that in your first attempt, you are calling
(add_timing(mean))(runif(1e7)
and with the compose syntax you are calling something more similar to
add_timing(mean(runif(1e7))
These are not exactly equivalent. Actually, the pryr compose function is really expanding the syntax to something more like
x <- runif(1e7)
x <- mean(x)
x <- add_timing(x)
Maybe looking at this will help
a <- function(x) {print(paste("a:", x));x}
b <- function(x) {print(paste("b:", x));x}
x <- pryr::compose(a,b)(print("c"))
# [1] "c"
# [1] "b: c"
# [1] "a: c"
Notice how a isn't called until after b. This means that a would have no way to time b. compose would not be an appropriate way to create a timer wrapper.
The issue is that pryr::compose is aimed at doing something completely different from what you're trying to do in your initial example. You want to create a function factory (called add_timing), which will take a function as input and return a new function as output that does the same thing as the input function but with an additional time printing. I would write that as follows:
add_timing <- function(FUN) { function(...) { print(system.time(r <- FUN(...))); r }}
mean(1:5)
# [1] 3
add_timing(mean)(1:5)
# user system elapsed
# 0 0 0
# [1] 3
The compose function, by contrast, returns a function that represents a series of functions to be evaluated in sequence. The examples in ? compose are helpful here. Here's an example that builds on that:
add1 <- function(x) x + 1
times2 <- function(x) x * 2
# the following two are identical:
add1(1)
# [1] 2
compose(add1)(1)
# [1] 2
# the following two are identical:
times2(1)
# [1] 2
compose(times2)(1)
# [1] 2
compose becomes useful for nesting, when the order of nesting is important:
add1(times2(2))
# [1] 5
compose(add1, times2)(2)
# [1] 5
times2(add1(2))
# [1] 6
compose(times2, add1)(2)
# [1] 6
This means that the reason your example does not work is because your functions are not actually nested in the way that compose is intended to work. In your example, you're asking system.time to, for example, calculate the time to evaluate 3 (the output of mean) rather than the time to evaluate mean(1:5).