R when debugging, is there a way to skip a specific statement? - r

I think most people has met the same problem with me
f1 = function(){
function1() #takes 1hour
b = function2() #takes 2hours
c = function3(b)
statement1
statement2
...}
suppose function1 and function2 is very time consuming, I want to skip at least one of them to see if the rest part of my function works
question1:
Is there a way to skip function1?
question2:
Is there a way to skip function2? this function2 produce result b which is critical for the function to continue, In java there is a way to hack value for b and make the process continue, is that also possible in R?

1) When in the debugger you can redefine the functions on the spot. For example, any time before getting to the point where function1 is invoked enter this into the debugger:
function1 <- list
Now invoking function1() actually invokes list() .
This could alternately be done outside of f1 before invoking it. In that case we may wish to store function1 in another name first to make it easy to revert back to it.
function1.orig <- function1
function1 <- list
Later, after we have completed our debugging, we can revert function1 back by writing:
function1 <- function1.orig
2) For function2 you may wish to redefine it as follows where 32 is the critical value needed later.
function2 <- function() 32

Related

Plus parameter to R script

I have made a pretty big package in R and I have collected a lot of smaller scripts in it. Later on it turned out that I may need to configure it a bit more than what I have made. Here is an example:
analyse <- function(param1,param2,param3,...){
function1 <- function(param1,param2,param3){...}
function2 <- function(param1,param2,param3){...}
function3 <- function(param1,param2,param3){...}
}
As you can see, this function have 3 function inside, and all of them have their parameters. When I call it:
analyse(param1=value1, param2=value2, param3=value3)
My question is, that is it possible to pass parameters to the inner functions as well? And what if the inner functions share a similar name parameter. For example function1 and 2 have the parameter name maxLength and I would like function1 to be maxLength=2 and function2 to be maxLength=10.
I would imagine it like this when calling:
analyse(param1=value1, param2=value2, param3=value3, paramToInnerFunct1=value1, paramToInnerFunct3=value1)
In my case if I give a plus parameter what would go to an inner function to the calling nothing happens.
Is there a way to deal with my problem?
Thank you in advance!
the simple solution is to just add the additional parameters like this:
analyse <- function(param1,param2,param3,
paramToInnerFunct1,paramToInnerFunct3,...){
function1 <- function(param1,param2,param3,paramToInnerFunct1){...}
function2 <- function(param1,param2,param3){...}
function3 <- function(param1,param2,param3,paramToInnerFunct3){...}
}
Edit:
maybe it works without named arguments (...) in your function 'analyse', but you would need the arguments in your 'function1'... though like this:
analyse <- function(param1,param2,param3,...){
function1 <- function(param1,param2,param3,paramToInnerFunct1){...}
function2 <- function(param1,param2,param3){...}
function3 <- function(param1,param2,param3,paramToInnerFunct3){...}
}
Another idea:
if you define the additional arguments like 'paramToInnerFunct1' in your global environment, you still can use them within the 'function1' like:
paramToInnerFunct1 <- "whatever object goes here"
function1 <- function(param1,param2,param3){
# use paramToInnerFunct1 from your global environment here
}
Hope that helps,
Samuel

Manually interrupt a loop in R and continue below

I have a loop in R that does very time-consuming calculations. I can set a max-iterations variable to make sure it doesn't continue forever (e.g. if it is not converging), and gracefully return meaningful output.
But sometimes the iterations could be stopped way before max-iterations is reached. Anyone who has an idea about how to give the user the opportunity to interrupt a loop - without having to wait for user input after each iteration? Preferably something that works in RStudio on all platforms.
I cannot find a function that listens for keystrokes or similar user input without halting until something is done by the user. Another solution would be to listen for a global variable change. But I don't see how I could change such a variable value when a script is running.
The best idea I can come up with is to make another script that creates a file that the first script checks for the existence of, and then breaks if it is there. But that is indeed an ugly hack.
Inspired by Edo's reply, here is an example of what I want to do:
test.it<-function(t) {
a <- 0
for(i in 1:10){
a <- a + 1
Sys.sleep(t)
}
print(a)
}
test.it(1)
As you see, when I interrupt by hitting the read button in RStudio, I break out of the whole function, not just the loop.
Also inspired by Edo's response I discovered the withRestarts function, but I don't think it catches interrupts.
I tried to create a loop as you described it.
a <- 0
for(i in 1:10){
a <- a + 1
Sys.sleep(1)
if(i == 5) break
}
print(a)
If you let it go till the end, a will be equal to 5, because of the break.
If you stop it manually by clicking on the STOP SIGN on the Rstudio Console, you get a lower number.
So it actually works as you would like.
If you want a better answer, you should post a reproducible example of your code.
EDIT
Based on the edit you posted... Try with this.
It's a trycatch solution that returns the last available a value
test_it <- function(t) {
a <- 0
tryCatch(
for(i in 1:10){
a <- a + 1
message("I'm at ", i)
Sys.sleep(t)
if(i==5) break
},
interrupt = function(e){a}
)
a
}
test_it(1)
If you stop it by clicking the Stop Sign, it returns the last value a is equal to.

Check if a function is called inside another function

Let say I have the function
mean_wrapper <- function(x) {
mean(x)
}
How can I check if the mean function is called?
An use case is for instance If I want to check this behavior in a unit test.
EDIT:
I make another exampe to be clearer. Let consider this function:
library(readr)
library(magrittr)
read_data <- function(file_name) {
read_csv(file_name) %>%
validate_data()
}
The aim of read_data is to read a CVS file and validate it. validate_data performs some checks on the data. It raises an error if one of them fail, otherwise returns the input object.
I want to test both functions but I don't want replicate the same tests I wrote for validate_data in the case of read_data. Anyway I have to check that the latter function has been called in read_data, so I wolud like to write a test that does this for me.
You could trace mean:
trace(mean, tracer = quote(message("mean was called")))
mean_wrapper(3)
#Tracing mean(x) on entry
#mean was called
#[1] 3
untrace(mean)
#Untracing function "mean" in package "base"
Instead of a message you can use anything (e.g., assignment to a variable in the enclosing environment) as tracer.

FOR loops giving no result or error in R

I am running the following code:
disc<-for (i in 1:33) {
m=n[i]
xbar<-sum(data[i,],na.rm=TRUE)/m
Sx <- sqrt(sum((data[i,]-xbar)^2,na.rm=TRUE)/(m-1))
Sx
i=i+1}
Running it:
>disc
NULL
Why is it giving me NULL?
This is from the documentation for for, accessible via ?`for`:
‘for’, ‘while’ and ‘repeat’ return ‘NULL’ invisibly.
Perhaps you are looking for something along the following lines:
library(plyr)
disc <- llply(1:33, function(i) {
m=n[i]
xbar<-sum(data[i,],na.rm=TRUE)/m
Sx <- sqrt(sum((data[i,]-xbar)^2,na.rm=TRUE)/(m-1))
Sx
})
Other variants exists -- the ll in llply stands for "list in, list out". Perhaps your intended final result is a data frame or an array -- appropriate functions exist.
The code above is a plain transformation of your example. We might be able to do better by splitting data right away and forgetting the otherwise useless count variable i (untested, as you have provided no data):
disc <- daply(cbind(data, n=n), .(), function(data.i) {
m=data.i$n
xbar<-sum(data.i,na.rm=TRUE)/m
sqrt(sum((data.i-xbar)^2,na.rm=TRUE)/(m-1))
})
See also the plyr website for more information.
Related (if not a duplicate): R - How to turn a loop to a function in R
krlmlr's answer shows you how to fix your code, but to explain your original problem in more abstract terms: A for loop allows you to run the same piece of code multiple times, but it doesn't store the results of running that code for you- you have to do that yourself.
Your current code only really assigns a single value, Sx, for each run of the for loop. On the next run, a new value is put into the Sx variable, so you lose all the previous values. At the end, you'll just end up with whatever the value of Sx was on the last run through the loop.
To save the results of a for loop, you generally need to add them to a vector as you go through, e.g.
# Create the empty results vector outside the loop
results = numeric(0)
for (i in 1:10) {
current_result = 3 + i
results = c(results, current_result)
}
In R for can't return a value. The unique manner to return a value is within a function. So the solution here, is to wrap your loop within a function. For example:
getSx <- function(){
Sx <- 0
disc <- for (i in 1:33) {
m=n[i]
xbar <- sum(data[i,],na.rm=TRUE)/m
Sx <- sqrt(sum((data[i,]-xbar)^2,na.rm=TRUE)/(m-1))
}
Sx
}
Then you call it:
getSx()
Of course you can avoid the side effect of using a for by lapply or by giving a vectorized But this is another problem: You should maybe give a reproducible example and explain a little bit what do you try to compute.

R Script - How to Continue Code Execution on Error

I have written an R script which includes a loop that retrieves external (web) data. The format of the data are most of the time the same, however sometimes the format changes in an unpredictable way and my loop is crashing (stops running).
Is there a way to continue code execution regardless the error? I am looking for something similar to "On error Resume Next" from VBA.
Thank you in advance.
Use try or tryCatch.
for(i in something)
{
res <- try(expression_to_get_data)
if(inherits(res, "try-error"))
{
#error handling code, maybe just skip this iteration using
next
}
#rest of iteration for case of no error
}
The modern way to do this uses purrr::possibly.
First, write a function that gets your data, get_data().
Then modify the function to return a default value in the case of an error.
get_data2 <- possibly(get_data, otherwise = NA)
Now call the modified function in the loop.
for(i in something) {
res <- get_data2(i)
}
You can use try:
# a has not been defined
for(i in 1:3)
{
if(i==2) try(print(a),silent=TRUE)
else print(i)
}
How about these solutions on this related question :
Is there a way to `source()` and continue after an error?
Either parse(file = "script.R") followed by a loop'd try(eval()) on each expression in the result.
Or the evaluate package.
If all you need to do is a small piece of clean up, then on.exit() may be the simplest option. It will execute the expression "when the current function exits (either naturally or as the result of an error)" (documentation here).
For example, the following will delete my_large_dataframe regardless of whether output_to_save gets created.
on.exit(rm("my_large_dataframe"))
my_large_dataframe = function_that_does_not_error()
output_to_save = function_that_does_error(my_large_dataframe)

Resources