Create a list member variable by value - r

I know that it is possible to create a variable by values. A e.g. is described here and here. Now I want to know is it possible to create in a similar way the member variable from list a by the value of x?
x<-"name"
a<-list( [here should place the value of x to declare the variable "name"]=1:5)
I dont searching for a workaround like changing dimnames after initialisation, because I like to do it with an S4 object initialisation.

I think you need this one:
x<-"name"
a<-list()
a[[x]] <- 1:5
result
> a
$name
[1] 1 2 3 4 5

Related

How do you solve "could not find function "deparse<-" | "as.name<-" | "eval<-"" errors when trying to dynamically name dataframes in R? [duplicate]

I am using R to parse a list of strings in the form:
original_string <- "variable_name=variable_value"
First, I extract the variable name and value from the original string and convert the value to numeric class.
parameter_value <- as.numeric("variable_value")
parameter_name <- "variable_name"
Then, I would like to assign the value to a variable with the same name as the parameter_name string.
variable_name <- parameter_value
What is/are the function(s) for doing this?
assign is what you are looking for.
assign("x", 5)
x
[1] 5
but buyer beware.
See R FAQ 7.21
http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f
You can use do.call:
do.call("<-",list(parameter_name, parameter_value))
There is another simple solution found there:
http://www.r-bloggers.com/converting-a-string-to-a-variable-name-on-the-fly-and-vice-versa-in-r/
To convert a string to a variable:
x <- 42
eval(parse(text = "x"))
[1] 42
And the opposite:
x <- 42
deparse(substitute(x))
[1] "x"
The function you are looking for is get():
assign ("abc",5)
get("abc")
Confirming that the memory address is identical:
getabc <- get("abc")
pryr::address(abc) == pryr::address(getabc)
# [1] TRUE
Reference: R FAQ 7.21 How can I turn a string into a variable?
Use x=as.name("string"). You can use then use x to refer to the variable with name string.
I don't know, if it answers your question correctly.
strsplit to parse your input and, as Greg mentioned, assign to assign the variables.
original_string <- c("x=123", "y=456")
pairs <- strsplit(original_string, "=")
lapply(pairs, function(x) assign(x[1], as.numeric(x[2]), envir = globalenv()))
ls()
assign is good, but I have not found a function for referring back to the variable you've created in an automated script. (as.name seems to work the opposite way). More experienced coders will doubtless have a better solution, but this solution works and is slightly humorous perhaps, in that it gets R to write code for itself to execute.
Say I have just assigned value 5 to x (var.name <- "x"; assign(var.name, 5)) and I want to change the value to 6. If I am writing a script and don't know in advance what the variable name (var.name) will be (which seems to be the point of the assign function), I can't simply put x <- 6 because var.name might have been "y". So I do:
var.name <- "x"
#some other code...
assign(var.name, 5)
#some more code...
#write a script file (1 line in this case) that works with whatever variable name
write(paste0(var.name, " <- 6"), "tmp.R")
#source that script file
source("tmp.R")
#remove the script file for tidiness
file.remove("tmp.R")
x will be changed to 6, and if the variable name was anything other than "x", that variable will similarly have been changed to 6.
I was working with this a few days ago, and noticed that sometimes you will need to use the get() function to print the results of your variable.
ie :
varnames = c('jan', 'feb', 'march')
file_names = list_files('path to multiple csv files saved on drive')
assign(varnames[1], read.csv(file_names[1]) # This will assign the variable
From there, if you try to print the variable varnames[1], it returns 'jan'.
To work around this, you need to do
print(get(varnames[1]))
If you want to convert string to variable inside body of function, but you want to have variable global:
test <- function() {
do.call("<<-",list("vartest","xxx"))
}
test()
vartest
[1] "xxx"
Maybe I didn't understand your problem right, because of the simplicity of your example. To my understanding, you have a series of instructions stored in character vectors, and those instructions are very close to being properly formatted, except that you'd like to cast the right member to numeric.
If my understanding is right, I would like to propose a slightly different approach, that does not rely on splitting your original string, but directly evaluates your instruction (with a little improvement).
original_string <- "variable_name=\"10\"" # Your original instruction, but with an actual numeric on the right, stored as character.
library(magrittr) # Or library(tidyverse), but it seems a bit overkilled if the point is just to import pipe-stream operator
eval(parse(text=paste(eval(original_string), "%>% as.numeric")))
print(variable_name)
#[1] 10
Basically, what we are doing is that we 'improve' your instruction variable_name="10" so that it becomes variable_name="10" %>% as.numeric, which is an equivalent of variable_name=as.numeric("10") with magrittr pipe-stream syntax. Then we evaluate this expression within current environment.
Hope that helps someone who'd wander around here 8 years later ;-)
Other than assign, one other way to assign value to string named object is to access .GlobalEnv directly.
# Equivalent
assign('abc',3)
.GlobalEnv$'abc' = 3
Accessing .GlobalEnv gives some flexibility, and my use case was assigning values to a string-named list. For example,
.GlobalEnv$'x' = list()
.GlobalEnv$'x'[[2]] = 5 # works
var = 'x'
.GlobalEnv[[glue::glue('{var}')]][[2]] = 5 # programmatic names from glue()

Assign to list index in specific environment using `get`

If I make an environment with a list in it, and want to assign values to that list, why does the following fail when using get and assign?
res <- new.env()
res$calls <- vector("list", 100)
res$counter <- 1
## works fine
res$calls[[1]] <- 1
## Fails, why?
get("calls", envir=res)[[get("counter", envir=res)]] <- 2
## doesnt make the assignment
val <- get("calls", envir=res)[[get("counter", envir=res)]]
assign("val", 2, envir=res)
I think the following will address your issue:
get("calls", envir=res)[[get("counter", envir=res)]] <- 2 fails because get is not a replacement function. On the other hand res$calls[[1]] <- 1 is actually a replacement function which you can see if you type help('[[<-'). This is the function used when you make an assignment. I think the reason why get has no replacement counterpart i.e. (get<-) is that there is a specific function to do this, which is called assign (as per #TheTime 's comment).
For the second case val <- get("calls", envir=res)[[get("counter", envir=res)]] is created in the global environment. When you use assign("val", 2, envir=res) a res$val variable is created inside the res environment which you can see below:
> res$val
[1] 2
However, val remains the same on the global environment as 1:
> val
[1] 1
So, You probably won't be able to do the assignment with either get or assign. get won't allow it because it is not a replacement function and ?assign mentions:
assign does not dispatch assignment methods, so it cannot be used to set elements of vectors, names, attributes, etc.
So, you can just use the normal [[<- assignment method. #Frank in the comments provides a nice way like:
res[[ "calls" ]][[ res[["counter"]] ]] <- 2

Why did a show up in my table name?

I ran this in R:
a <- factor(c("A","A","B","A","B","B","C","A","C"))
And then I made a table
results <- table(a)
but when I run
> attributes(results)
$dim
[1] 3
$dimnames
$dimnames$a
But I'm confused why does a show up in my attributes? I've programmed in Java before and I thought variable names weren't supposed to show up in your functions .
R functions can not only see the data you pass to them, but they can see the actual call that was run to invoke them. So when you run, table(a) the table() function not only sees the values of a, but is also can see that those values came from a variable named a.
So by default table() likes to name each dimension in the resulting table. If you don't pass explicit names in the call via the dnn= parameter, table() will look back to the call, and turn the variable name into a character and use that value for the dimension name.
So after table() has ran, it has no direct connection to the variable a, it merely used the name of that variable as a character label of the results.
Many functions in R do this. For example this is similar to how plot(height~weight, data=data.frame(height=runif(10), weight=runif(10))) knows to use the names "weight" and "height" for the axis labels on the plot.
Here's a simple example to show one way this can be accomplished.
paramnames <- function(...) {
as.character(substitute(...()))
}
paramnames(a,b,x)
# [1] "a" "b" "x"
I think the only answer is because the designers wanted it that way. It seems reasonable to label table objects with the names of variables that formed the margins:
> b <- c(1,1,1,2,2,2, 3,3,3)
> table(a, b)
b
a 1 2 3
A 2 1 1
B 1 2 0
C 0 0 2
R was intended as a clone of S, and S was intended as a tool for working statisticians. R also has a handy function for working with table objects, as.data.frame:
> as.data.frame(results)
a Freq
1 A 4
2 B 3
3 C 2
If you want to build a function that performs the same sort of labeling or that otherwise retrieves the name of the object passed to your function then there is the deparse(substitute(.))-maneuver:
myfunc <- function(x) { nam <- deparse(substitute(x)); print(nam)}
> myfunc <- function(x) { nam <- deparse(substitute(x)); print(nam)}
> myfunc(z)
[1] "z"
> str(z)
Error in str(z) : object 'z' not found
So "z" doesn't even need to exist. Highly "irregular" if you ask me. If you "ask" myfunc what its argument list looks like you get the expected answer:
> formals(myfunc)
$x
But that is a list with an R-name for its single element x. R names are language elements, whereas the names function will retrieve it as a character value, "x", which is not a language element:
> names(formals(myfunc))
[1] "x"
R has some of the aspects of Lisp (interpreted, functional (usually)) although the dividing line between its language functions and the data objects seems less porous to me, but I'm not particularly proficient in Lisp.

In R, how to use values as the variable names

I know the function get can help you transform values to variable names, like get(test[1]). But I find it is not compatible when the values is in a list format. Look at below example:
> A = c("obj1$length","obj1$width","obj1$height","obj1$weight")
> obj1 <- NULL
> obj1$length=c(1:4);obj1$width=c(5:8);obj1$height=c(9:12);obj1$weight=c(13:16)
> get(A[1])
Error in get(A[1]) : object 'obj1$length' not found
In this case, how can I retrieve the variable name?
get doesn't work like that you need to specify the variable and environment (the list is coerced to one) separately:
get("length",obj1)
[1] 1 2 3 4
Do do it with the data you have, you need to use eval and parse:
eval(parse(text=A[1]))
[1] 1 2 3 4
However, I suggest you rethink your approach to the problem as get, eval and parse are blunt tools that can bite you later.
I think that eval() function will do the trick, among other uses.
eval(A[1])
>[1] 1 2 3 4
You could also find useful this simple function I implemented (based in the commonly used combo eval, parse, paste):
evaluate<-function(..., envir=.GlobalEnv){ eval(parse(text=paste( ... ,sep="")), envir=envir) }
It concatenates and evaluates several character type objects. If you want it to be used inside another function, add at the begining of your function
envir <- environment()
and use it like this:
evaluate([some character objects], envir=envir)
Try, for example
myvariable1<-"aaa"; myvariable2<-"bbb"; aaa<-15; bbb<-3
evaluate(myvariable1," * ",myvariable2).
I find it very usefull when I have to evaluate similar sentences with several variables, or when I want to create variables with automatically generated names.
for(i in 1:100){evaluate("variable",i,"<-2*",i)}

Switch Statements in R (Unpacking Arguments)

Google search doesn't return much on this. How do you unpack arguments in R?
For instance if I try to use switch in R like
switch("AA",c("AA"=5,"BB"=6))
I will get back c("AA"=5,"BB"=6) when in reality, I want 5.
Essentially, I want to be able to do switch("AA","AA"=5,"BB"=6) with a vector mapping.
This is a bit of a workaround, but try:
do.call("switch", append(list("AA"), list("AA"=5, "BB"=6)))
The do.call() allows you to pass a list of arguments into switch().
This is how switch was intended to be used. The first argument gets evaluated and match to the first elements of the succeeding pairlists:
aa <- "AA"
switch(aa,"AA"=5,"BB"=6)
#[1] 5
switch("BB","AA"=5,"BB"=6)
#[1] 6
At least that is the strategy for 'character' arguments. The process for numeric arguments is different. One needs to read the Details section of ?switch carefully.
Your example is rather short, mayby you could obtain demanded functionality this way :
my.vector = c("AA"=5,"BB"=6)
my.vector[names(my.vector ) == "AA"]
AA
5
?
> c("AA"=5,"BB"=6)["AA"]
AA
5
> c("AA"=5,"BB"=6)["BB"]
BB
6

Resources