R | replace environment name by a variable - r

a newbie question: I want to write a universal function which saves variables in a new environment. The name of the environment I want to give as argument in to the function.
#create environment
my.env <- new.env()
#variable to store the name of the environment
env_n<-"my.env"
# now safe a variable a with value 1 to my.env
my.env$a=1 #working
But I want to have a universal solution which works for many cases, there for I want to use the variable which stores the name of the environment. Something like:
#Things I tried
env_n$a=1 #not working
assign(a, 1, envir=env_n)
Can you help me? Thanks a lot!

The first parameter to assign() should be a character value, not a symbol. And the envir= parameter should be a proper environment, not a character value. If you want to get the value of a variable given a character value of the variable name, you use get(). This should work
assign("a", 1, envir=get(env_n))
But this is a very unusual operation for a "newbie" to be using. I would take a step back and look and what you are trying to do and see if there isn't a more "R-like" way to do things.

Related

How do I use get() in R to access a variable with another variable?

I have a loop which is running over a vector containing names of a few tens of dataframes that are in my environment. On each iteration, I want to access the dataframe using the name, and access a specific column within it. As I understand it, the best way to access a variable with a string is using get().
But when I try and do this (with name being a variable containing the string "first.name"):
get(column.name, name)
I get the error:
Error in as.environment(pos) : no item called "first.name" on the search list
It does work if I try to run:
get(column.name, first.name)
So, assuming that get() is the right function for this, what am I doing wrong?
Reproduceable example:
my.df <- as.data.frame(x = seq(1:10), y = rnorm(10))
name <- "my.df"
get("x",name)
We may need to use
get(name)[[column.name]]

Referencing a function parameter in R

I'm working on a function and need to know how to reference the incoming parameters.
For example, in python or lots of other languages, you can reference the input parameters something like this:
sys.argv[1:].
How can I reference the name of a parameter in R?
The specific problem I'm trying to solve is I want to capture the string value of the incoming parameter, so I can paste it as a concentration with a list of column_names I want to iterate through.
Here's the head of the function call, just so you can see the incoming parameter:
function(df_in)
So here's an example of the code I am writing and I want the string value of the dataframe_in, not the object that it references.
col_name <-paste(df_in,varnames[i],sep="$")
if df_in contained "my_df" and the current column_name is my_col, I'm trying to have col_name in the example above set to my_df$my_col.
I was thinking of using the get() function but quite sure how to apply it in this situation.
Thanks
Try something along these lines:
fn1 <- function(df_in){ in_nam <- deparse(substitute(df_in) )
col_names <-paste(in_nam, names(df_in), sep="$")
cat(col_names) }
> dfrm <- data.frame(a=1:10, b=letters[1:10])
> fn1(dfrm)
#dfrm$a dfrm$b
You didn't say what varnames was supposed to be so I'm guessing you want the column names from the object. BTW, don't expect to be able to reference the column values with those character values. They are no longer language objects.

Unexpected R behavior with function parameter

Am R newb. I coded a function that uses 3 parameters. In my code i use one of the parameters to help me read files from a directory. There are 100 files in the directory. The code works fine when I pass it all the function parameters and specify the files i want to read.
functionX(var1, var2, id) and functionX(var1, var2, id = 1:100)
## Below is the first line of code for me that uses "id".
sub.file.names <- file.names[id] ### Get file names
The odd thing is that when a value for "id" is not passed to the function initially (or set with a 1:100 default), the code seems to read all the file names anyway. And it does so even though a value for "id" has never been established.
It's as if R somehow treats the two functions below the same when the user omits passing a value to "id" when executing the function ... eg, functionx("var1", "var2") ## and does not pass any id variable
functionx(var1, var2, id)
functionx(var1, var2, id = 1:100)
Any pointers on why this is happening would be great to know. I feel the answer is obvious, but have not been able to figure it out.
Let me try to explain what is happening with a simple example. Consider the following function
foo = function(i){
LETTERS[i]
}
When you try foo(), you will notice that the function returns all 26 uppercase letters. Why does that happen? Well, everything in R is a function. So when you say LETTERS[i], you are essentially calling the function [. So, the function call is
`[`(LETTERS, i)
Since i is missing, this call is executed as [(LETTERS) (essentially LETTERS[]) which returns all elements of the vector. Note that this occurs because the [ function allows for the i argument to be missing while calling it. Check ?[
If you want the function to act differently when id is missing, either check for missing(id), or explicitly set it to NULL as default. So, if you do
foo2 = function(i = NULL){
LETTERS[i]
}
foo2() will return a zero length character vector.

How to remove selected R variables without having to type their names

While testing a simulation in R using randomly generated input data, I have found and fixed a few bugs and would now like to re-run the simulation with the same data, but with all intermediate variables removed to ensure it's a clean test.
Is there a way to remove several dozen manually selected variables from the workspace without having to:
a) clobber the entire workspace, e.g. rm(list=ls()), or b) type each variable name, e.g. remove(name1, name2, ...)?
Ideal solution would be to use ls() to inspect the definitions and then pick out the indices of the ones I want to remove, e.g.
ls() # inspect definitions
delme <- c(3,5,7:9,11,13) # names selected for removal
remove(ls()[delme]) # DESIRED SOLUTION -- doesn't quite work this way
(In hindsight, I should have used a fixed seed to generate the random input data, which allow clearing everything and then re-running the test...)
There is a much simpler and more direct solution:
vars.to.remove <- ls()
vars.to.remove <- temp[c(1,2,14:15)]
rm(list = vars.to.remove)
Or, better yet, if you are good about variable naming schemes, you can use the following pattern matching strategy:
E.g. I name all temporary variables with the starting string "Temp."
... so, you can have Temp.Names, Temp.Values, Temp.Whatever
The following produces the list of variables that match this pattern
ls(pattern = "^Temp\\.")
So, you can remove all unneeded variables using ONE line of code, as follows:
rm(list = ls(pattern = "^Temp\\."))
Hope this helps.
Assad, while I think the actual answer to the question is in the comments, let me suggest this pattern as a broader solution:
rm(list=
Filter(
Negate(is.na), # filter entries corresponding to objects that don't meet function criteria
sapply(
ls(pattern="^a"), # only objects that start with "a"
function(x) if(is.matrix(get(x))) x else NA # return names of matrix objects
) ) )
In this case, I'm removing all matrix object that start with "a". By modifying the pattern argument and the function used by sapply here, you can get pretty fine control over what you delete, without having to specify many names.
If you are concerned that this could delete something you don't want to delete, you can store the result of the Filter(... operation in a variable, review the contents, and then execute the rm(list=...) command.
Try
eval(parse(text=paste("rm(",paste(ls()[delme],sep=","),")")))
I had a similar requirement. I pulled all the elements I needed to a list:
varsToPurge = as.list(ls())
I then reassign the few values I wish to keep with new variable names which will not be in the variable varsToPurge. After that I looped through the elements
for (j in 1:length(varsToPurge)){
rm(list = as.character(varsToPurge[j]))
}
Do a little garbage collecting, and you maintain a clean environment as you go through your code.
gc()
You can also use a vector of row numbers you wish to keep instead and run through the vector in the loop but it won't be as dynamic if you add rough work you wish to remove.

How do I use a variable to name another variable in R? [duplicate]

This question already has answers here:
How to name variables on the fly?
(6 answers)
r - how to use a variable in a variable
(3 answers)
Closed 9 years ago.
I have a function that uses readline to allow the user to enter the name they want to give for a variable I will be creating for them. Let's call this "USER.DEFINED.VARIABLE". It contains the name I want to use for another variable. Let's say that "USER.DEFINED.VARIABLE" gets set by readline to be "jimsfilename".
I know I can assign value to a variable named "jimsfilename" using:
assign(USER.DEFINED.VARIABLE,c(1,2,3,4,5))
"jimsfilename" will now have 1,2,3,4,5 in it. However, how do I now fuss with "jimsfilename", given that I don't (before readline assigns it to USER.DEFINED.VARIABLE) know what its name is?
In other words, lets say I now want to add 1 to every value in jimsfilename. I can't do:
USER.DEFINED.VARIABLE <- USER.DEFINED.VARIABLE + 1 # can't do this
because "USER.DEFINED.VARIABLE" is actually a text string name. I want instead to refer to jimsfilename, but all I have is USER.DEFINED.VARIABLE to indicate it. I'm sure this is something easy...
It depends bit on what you want to do, but here's an example of using get function:
x = 1
get("x") + 1
2
assign("name", get("x") + 1)
name
2
Why not just do all the manipulation of the variable (adding 1 or other changes) to a local copy of the variable with your own name, then at the end of the function/script/whatever do the assigning or other saving? That would be much simpler than creating the variable then having to use get to get a copy, change it, and assign it again.
Even better is to use your own variable name inside of a function, then just return the result and let the user decide what to name it at that point. This is the much more Rish way of doing things, it is best to not use the assign function at all. Most things that can be done using assign can be done much simpler by using a list and subscripting.
Functions should not change anything in the global environment, just return any values that the user might need and let the user make the assignment.
You can use eval and parse. The later interprets text as if it was an input in the console. The first evaluates the expression (generated by parse, for instance). Example:
> varname <- "user.defined.variable"
> varvalue <- 42
> eval(parse(text=paste(varname, varvalue, sep=" <- ")), envir=.GlobalEnv)
> ls()
[1] "user.defined.variable" "varname" "varvalue"
> user.defined.variable
[1] 42
Note that I've choosen the global environment as the destination for the new variable. You can make the appropriate changes if that is not the case.
To refer to the new variable later, you can use as.symbol. Just evaluate it under the environment where you assigned the new variable:
> eval(as.symbol(varname), envir=.GlobalEnv)
[1] 42
You can also use substitute to create expressions that eval can understand:
> eval(substitute(x+1, list(x=as.symbol(varname))), envir=.GlobalEnv)
[1] 43
To make changes to the new variable, just creat assignments expressions and evaluate them:
> eval(substitute(x <- x*10, list(x=as.symbol(varname))), envir=.GlobalEnv)
> eval(as.symbol(varname), envir=.GlobalEnv)
[1] 420

Resources