How do I remove an object from within a function environment in R? - r

How do I remove an object from the current function environment?
I'm trying to achieve this:
foo <- function(bar){
x <- bar
rm(bar, envir = environment())
print(c(x, is.null(bar)))
}
Because I want the function to be able to handle multiple inputs.
Specifically I'm trying to pass either a dataframe or a vector to the function, and if I'm passing a dataframe I want to set the vector to NULL for later error handling.
If you want, you can watch my DepthPlotter script, where I want to let the second function check if depth is a dataframe, and if so, assign it to df in stead and remove depth from the environment.

Here is a very brief sketch of how to set this up using S3 method dispatch.
First, you define your generic:
DepthPlotter <- function(depth,...){
UseMethod("DepthPlotter", depth)
}
Then you define methods for specific classes of the argument depth. As a very basic example in your case, you might create only two, a data.frame method and a default method to handle the vector case:
DepthPlotter.default <- function(depth, variable, ...){
#Here you write a function assuming that depth is
# anything but a data frame
}
DepthPlotter.data.frame <- function(depth,...){
#Here you'd write a function that assumes
# that depth is a data frame
}
And then you can call DepthPlotter() using either type of argument and the correct function will be run based upon the result of class(depth).
The example I've sketched out here is a little crude, since I've used a default method to handle the vector case. You could write .numeric and .integer methods to handle numeric or integer vectors more specifically. In my example, the .default method will be called for any case other than data.frame, so if you go this route you'd want to write some code in there that checks for strange cases like depth being a complicated list, or other odd object, if you think there's a chance something like that might be passed to the function.

Related

Is it possible to make a R Shiny reactive function that accepts arguments like a normal function?

I have a situation where I have a reactive function that I would like to be used in several different plots, but to be calling/checking different parts of a dataframe stored as reactiveValues.
If I had a normal function I could call it and pass it an argument to index a specific column of the reactive values e.g.,:
my_function <- function(column) {what the function does}
Then when calling the function:
my_function(column = 3)
But for a reactive function I don't see how I can do something like this.
my_function <- reactive({what the function does})
At the moment, I can just make multiple versions of essentially the same function that call different indexes but that is a lot of extra lines of code as the function is quite long.
The situation is also not one where I see a simple way of using another reactive value that can be called inside the reactive function that would appropriately call the right column index in all cases.
Is there a way to define the reactive function so that when it is called, I can pass it an argument?

Insert a Function Name into a Call

I have a long script wherein I have a section at the top which is dedicated to assumptions and other hardcodes. By means of context, it's an asset allocation script wherein one of the hardcodes that is chosen is the method by which momentum is calculated, for which I have various functions. I realize that one way in which I could change the code is simply to change the function used in the body of the code; however, my preference would be to leave the body untouched and only change the name of the function to be used within the assumptions section.
By means of an extremely simple toy example, let's say I have the following two lines of code:
selected_function = "sum"
temp_data = c(2,3,4)
How would I allow whichever function is saved in the variable selected_function to be the calling function on the temp_data data set (i.e., if I want to change it to "mean", etc.) and allow that function to be applied to the data.
If you have a function name as a string, you get can get the function itself with getFunction(). That will return a function and you can then pass your values to that returned function. For example.
selected_function = "sum"
temp_data = c(2,3,4)
getFunction(selected_function)(temp_data)

R: Not to look for variables outside a function if they do not exist within it

This function is OK in R:
f <- function(x) {
x + y
}
Because if the variable y is not defined inside the function f(), R will look for it outside the environment of the function, in its parent environment.
Apart from the fact that this behavior can be a bug generator, what is the point of functions having input parameters? Anyway, all the variables inside a function can be searched outside of it.
Is there any way not to look for variables outside a function if they do not exist within the function?
Some reasons for using parameters that came to my mind:
Without parameters, users have to define variables before using the function, and these variable names need to match the variable names used within the function -- this is impractical.
How is anyone supposed to know/remember the names of the variables within a function? How do I know which variables within a function are purely local, and which variables have to exist outside of the function?
Input parameters can be passed directly as values or as a variable (and the variable name does not matter).
Input parameters communicate the intended usage of the function; it is clear what data is needed to operate it (or at the very least: how many values need to be inserted by the user of the function)
Input parameters can be documented properly using Rd files (or roxygen syntax)
I am sure there are many other reasons to use input parameters.
M. Papenberg provides a very good explanation.
Here's a quick addendum how to make a function not look for objects in parental environments:
Just provide them in the parameter list! This might sound stupid, but that's what you should always do unless you have good reason to do otherwise. In your example only x is passed to the function. So, if the idea here is that x should be returned if y doesn't exist, you can go for default parameters. In this case this could be done as
f <- function(x, y = 0) {
x + y
}

Naming columns of coefficient matrix in a VAR

I am searching for a fast and simple way to give comprehensible names to the columns of a VAR-coefficient matrix.
What I would like to use is the function VAR.names, which is used in the function VAR.est() in the VAR.etp-package. When I use the function VAR.est(), this works perfectly, but as soon as I modify VAR.est (by adding another element to the list of values which are returned), I receive an error message stating "could not find function VAR.names".
I could not find any information on the function VAR.names.
Example:
library(VAR.etp)
data(dat)
M=VAR.est(dat,p=2,type="const")
M$coef
Another possibility would be to use a loop as in the function VAR() from the vars package, but if VAR.names would actually work, this would be a lot more elegant!

How does one pass multiple data types in llply?

I have a function that requires both a S4 object and a data frame as arguments.
But functions like lapply and llply will only allow one list and one function.
example: new_list=llply(list, function)
I could make a single list with alternating S4 object and data but llply will push one list item at a time which means that it will either be the S4 object or the data (the function cannot perform with just one or the other).
In some sense what I am looking for is akin to a 2D list (where each row has the S4 obj and data and a row gets pushed through at a time).
So how would I make this work?
Here's a more general version of my problem. If I have a function like so:
foobar <- function(dat, threshold=0.5, max=.99)
{
...
}
and I wanted to push a list through this function, I could do:
new_list=llply(list, foobar)
but if I also wanted to pass a non-default value for threshold or max, how would I do so in this context?
Functions like lapply typically have a ... parameter of arguments which get passed to the function. Eg:
lapply(list, foobar, somearg='nondefaultvalue')
If you have multiple varying parameters (eg a different somearg value for each element in list), then you would either pack them as pairs in a list, or turn to a function like mapply:
mapply(foobar, list, somearg=c('vectorof', 'nondefault', 'values')
May be you can try this:
Make each list item itself a list, which contains a S4 object and a data frame.
Just a suggestion, I'm not quite sure if this works.

Resources