Search code examples
rvariablesgetenvironment-variablesassign

Assign value to element of list using variable name in R


I wish to recursively modify the slot slot1 of several objects that share part of the name. I know how to modify the objects (obj_num1, obj_num2, obj_num3) using assign, but what I don't know how to do is to modify/access only part of the object by selecting the slot (and, ideally, a single column of the slot, if the object is a data frame/matrix).


## creating simpler objects
obj_num1 <- list(a=runif(10), b='original')
obj_num2 <- list(a=runif(10), b='original')
obj_num3 <- list(a=runif(10), b='original')

## modifying the objects with assign
for(it in 1:3){
    assign(paste0('obj_num', it), list(a=runif(10), b='modified'))
}
## it works

## but what if the object has a slot? --this is what I don't know how to do

setClass("myclass",
    representation = representation(
    slot1="character"
    ))

obj_num1 <- new('myclass', slot1='original')
obj_num2 <- new('myclass', slot1='original')
obj_num3 <- new('myclass', slot1='original')

for(it in 1:3){
    assign(paste0('obj_num', it, '@slot1'), 'modified') ## nothing changes
}

help would be appreciated!

How to assign a name to a specific element of a vector in R, although similar, does not answer the question


Solution

  • You should generally avoid get/assign. It's an anti-pattern in R. It's better to work with items in lists and apply functions over lists rather than create a bunch of objects in the global environment that have indexes in their name. Note that you can only use variable names with assign something like obj_num1@slot1 is not a name, it's an expression that evaluates to a value. You can kind of get around that with geting the value, then updating it with the slot<- function and assinging the result. For example

    for(it in 1:3){
      assign(paste0('obj_num', it), `slot<-`(get(paste0('obj_num', it)), 'slot1', TRUE, 'modified'))
    }
    

    But if you had things in a list you could just do

    objs <- list(
      obj_num1,
      obj_num2,
      obj_num3
    )
    
    lapply(objs, function(x) {
      x@slot1 <- "modified"
      x
    })