Plus parameter to R script - r

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

Related

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

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

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.

How to get the variable name in a function call?

Sorry for my poor English but I can not think of a title that could concisely describe my problem, which is a little bit complicated than the title suggests.
Here is what I'd like to achieve:
In the global environment, one can get the name of a variable, say xyz, by calling deparse(substitute(xyz)). I need to use this at several places in my code so I decided to make it a function: getVarName <- function(x){deparse(substitute(x))}.
Then I write some function myfunc in which I need to call getVarName:
myfunc <- function(x){cat(getVarName(x))}
Now here is the problem: when I call myfunc(y), instead of printing out y, it still prints out x. I suspect it has something to do with the environment in which substitute() does the trick, but got no luck in that direction.
What do I have to do to make it right?
P.S. It'll be nice if some could edit the title with a better description of this question, thank you!
From what I saw while testing your code, it appears that deparse(substitute(x)) will only print out the name of the variable which was immediately below it in the call stack. In your example:
getVarName <- function(x){ deparse(substitute(x)) }
myfunc <- function(x){ cat(getVarName(x)) }
myfunc(y)
The call to getVarName() is processing a variable from myfunc() which was called x. In effect, the variable y which you passed is not part of the call stack anymore.
Solution:
Just use deparse(substitute(x)) directly in the function where you want to print the name of the variable. It's concise, and you could justify not having a helper function as easily as having one.
It is typically the kind of functional programmming problem where you can use a decorator:
decorator = function(f)
{
function(...)
{
print(as.list(match.call()[-1]))
f(...)
}
}
foo = function(x,y,z=2) paste0(x,y,z)
superFoo = decorator(foo)
Results:
> xx=34
> superFoo('bigwhale',xx)
[[1]]
[1] "bigwhale"
[[2]]
xx
[1] "bigwhale342"

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.

find all functions in a package that use a function

I would like to find all functions in a package that use a function. By functionB "using" functionA I mean that there exists a set of parameters such that functionA is called when functionB is given those parameters.
Also, it would be nice to be able to control the level at which the results are reported. For example, if I have the following:
outer_fn <- function(a,b,c) {
inner_fn <- function(a,b) {
my_arg <- function(a) {
a^2
}
my_arg(a)
}
inner_fn(a,b)
}
I might or might not care to have inner_fn reported. Probably in most cases not, but I think this might be difficult to do.
Can someone give me some direction on this?
Thanks
A small step to find uses of functions is to find where the function name is used. Here's a small example of how to do that:
findRefs <- function(pkg, fn) {
ns <- getNamespace(pkg)
found <- vapply(ls(ns, all.names=TRUE), function(n) {
f <- get(n, ns)
is.function(f) && fn %in% all.names(body(f))
}, logical(1))
names(found[found])
}
findRefs('stats', 'lm.fit')
#[1] "add1.lm" "aov" "drop1.lm" "lm" "promax"
...To go further you'd need to analyze the body to ensure it is a function call or the FUN argument to an apply-like function or the f argument to Map etc... - so in the general case, it is nearly impossible to find all legal references...
Then you should really also check that getting the name from that function's environment returns the same function you are looking for (it might use a different function with the same name)... This would actually handle your "inner function" case.
(Upgraded from a comment.) There is a very nice foodweb function in Mark Bravington's mvbutils package with a lot of this capability, including graphical representations of the resulting call graphs. This blog post gives a brief description.

Resources