Using get() with a list - r

Is there a way to use get() with a list object?
The functionality I'm looking for is akin to:
x <- list(a=c(1,2,3),b=c(4,5,6),c=c(7,8,9))
get(paste("x$a",sep=""))

This will work:
get("a", envir=list2env(x))
But that is more or less as useful as x[['a']]. It seems you might also be looking for the eval/parse route:
eval(parse(text="x$a"))

Specify the pos= argument:
> get("a",x)
[1] 1 2 3
In order for your example to work, you would need to evaluate the expression, since "x$a" isn't a valid name.
> eval(parse(text=paste("x$a",sep="")))
[1] 1 2 3

Maybe this alternative would work for you?
get("x")[["a"]]

Related

R - using the assign() function for subsetting an array

I have tried to get the gist of my problem in the following reproducible example :
mat <- matrix(3:6,nr=2,nc=2)
j=1
> eval(parse(text=paste0("m",c("a","b")[j],"t","[1,1]")))
[1] 3
> assign(paste0("m",c("a","b")[j],"t","[1,1]"),45)
> mat
[,1] [,2]
[1,] 3 5
[2,] 4 6
My problem is that mat[1,1] is still equal to 3 and not 45 as I would have expected.
A primer on R: "Every operation is a function call." What this means, in a practical sense for your question, is that you can't use assign() with more than just a name. mat[1,1] is not a name - it is the name mat and the function call [. So, using the expression mat[1,1] within assign will not work, because it is trying to find an R object named mat[1,1] (which I think is disastrous for a few reasons...)
This seems like a really weird use case. You might want to consider instead working in a function, which has its own environment that you can manipulate without working in the global environment.
Alternatively, you can do this:
eval(parse(text=paste0("m",c("a","b")[j],"t","[1,1] <- 45")))
eval(parse(text=paste0("m",c("a","b")[j],"t","[1,1]")))
I am struggling to think of a reason you would want to - but it is, in theory, possible. Basically, you just add the assignment to the text that you are parsing, then pass it to eval().

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

How to assign from a function with multiple outputs? [duplicate]

This question already has answers here:
How to assign from a function which returns more than one value?
(16 answers)
Closed 10 years ago.
Is there a way to output e.g. 2 objects without using list()?
my.fun=function(vector, index)
{
a=fun.a(vector, index)
b=fun.b(vector, index)
output=list(a,b)
}
Or to output 2 lists of objects? Considering that I could also have:
c=fun.a(vector, index)
d=fun.b(vector, index)
And wanted list(a,b) and another list(c,d) for the same function.
This is just a small example for what I am looking for, my function is applied to large objects and I export them as a list, however I would like to export also an intermidiate calculation. One option would be to merge all in the same list, but I would like to know if there is another solution to this.
You can only return one object in a function. But you have some other options. You could assign intermediate objects to the global environment (you need to be careful not to overwrite anything) or you could pass an environment to your function and assign objects to it.
Here's an example of the latter suggestion:
fun <- function(x, env) {
env$x2 <- x^2
x^3
}
set.seed(21)
x <- rnorm(10)
myEnv <- new.env()
fun(x, myEnv)
# [1] 4.987021e-01 1.424421e-01 5.324742e+00 -2.054855e+00 1.061014e+01
# [6] 8.125632e-02 -3.871369e+00 -8.171530e-01 2.559674e-04 -1.370917e-08
myEnv$x2
# [1] 6.288699e-01 2.727464e-01 3.049292e+00 1.616296e+00 4.828521e+00
# [6] 1.876023e-01 2.465527e+00 8.740486e-01 4.031405e-03 5.728058e-06
I found list2env ideal for what you're describing; the trickiest bit, for me, was working out what to give for the env parameter:
f=function(){
list(a=1,b="my string")
}
ret=f()
list2env(ret,env=environment())
#a=ret$a;b=ret$b #Same as previous line
print(a);print(b) #1 and "my string"
The return() object needs to be one thing ... a list or a vector. Since a list can be that "one thing" and a list can hold many things of many classes, all you need to di is initialize a list structure and then push things into it until you are ready to retrun that structure to the calling anvironment.
If you want to "push" individual items into the global (or other environment), you can use <<- or assign, although that is considered ugly practice and a violation of the paradigm of functional programming.
I believe you are limited to using lists, but you can combine them like:
> list(list(a=1, b=2), list(c=3, d=4))
[[1]]
[[1]]$a
[1] 1
[[1]]$b
[1] 2
[[2]]
[[2]]$c
[1] 3
[[2]]$d
[1] 4

Does R have 'dict' as in python or 'map' as in c++ do?

I am new to R programming. After checking some tutorial I picked up most things I needed, but one thing is still missing: the data structure map.
Does everybody know if R has dict? In which I can store (key, value) pairs?
Thanks!!
Yes it does and it is called list.
> x <- list(a=1, b="foo", c=c(1,1,2,3,5))
> x
$a
[1] 1
$b
[1] "foo"
$c
[1] 1 1 2 3 5
In Python it is called dict, for what it's worth.
Environments are also a candidate, and in many cases the best option.
e<-new.env(hash=T)
e$a<-1
e$b<-2
R> e$a
[1] 1
The disadvantage of a list is that it is a linear search.
There is the hash package..
Since array/vector elements can be named, you get some of the properties of a map/dictionary builtin.
x <- c(apple = 1, banana = 99, "oranges and lemons" = 33)
x["apple"]
x[c("bananas", "oranges and lemons")]
x[x == 99]
(If your values are of different types, then you need to use a list instead of a vector.)
The hash package as aforementioned does add a little overhead but does provide a flexible, intuitive methods for accessing the map/hash/dictionary. It should be very easy for users from another language to grok it.
A list is the best solution if the list has a small number of elements. (<200 or so).
An environment is best to use if you absolutely cannot tolerate a little overhead AND you do not want the flexible, intuitive methods.
The hash package is the best in most situations.
C-

Resources