0

I'm trying to assign values to specific indices of a long list of vectors (in a loop), where each vector is specified by a string name. The naive approach

testVector1 <- c(0, 0, 0)

vectorName <- "testVector1"
indexOfInterest <- 3

assign(x = paste0(vectorName, "[", indexOfInterest, "]"), value = 1)

doesn't work, instead it creates a new vector "testVector1[3]" (the goal was to change the value of testVector1 to c(0, 0, 1)).

I know the problem is solvable by overwriting the whole vector:

temporaryVector <- get(x = vectorName)
temporaryVector[indexOfInterest] <- 1
assign(x = vectorName, value = temporaryVector)

but I was hoping for a more direct approach.

Is there some alternative to assign() that solves this?

Similarly, is there a way to assign values to specific elements of columns in data frames, where both the data frames and columns are specified by string names?

Peter Z
  • 3
  • 1
  • why do you want to work on the object name rather than on the object itself? Using assign is almost always a hacky workaround and should be avoided (IMO) – mnist Oct 11 '22 at 09:36
  • @mnist because the number of vectors is fairly large (~40) and operated on using a loop (with slightly different things done for every vector), and 'indexable' using their names. The answer by SamR below using lists solves my problem, however. Is there a specific reason why assign should be avoided? – Peter Z Oct 11 '22 at 10:12
  • https://stackoverflow.com/q/17559390/8107362 – mnist Oct 11 '22 at 10:39

1 Answers1

1

If you must do this you can do it with eval(parse():

valueToAssign  <- 1
stringToParse  <- paste0(
    vectorName, "[", indexOfInterest, "] <- ", valueToAssign
)
eval(parse(text = stringToParse))

testVector1
# [1] 0 0 1

But this is not recommended. Better to put the desired objects in a named list, e.g.:

testVector1 <- c(0, 0, 0)

dat  <- data.frame(a = 1:5, b = 2:6)

l  <- list(
    testVector1 = testVector1,
    dat = dat
)

Then you can assign to them by name or index:


vectorName <- "testVector1"
indexOfInterest <- 3

dfName  <- "dat"
colName  <- "a"
rowNum  <- 3

valueToAssign  <- 1

l[[vectorName]][indexOfInterest]  <- valueToAssign
l[[dfName]][rowNum, colName]  <- valueToAssign

l
# $testVector1
# [1] 0 0 1

# $dat
#   a b
# 1 1 2
# 2 2 3
# 3 1 4
# 4 4 5
# 5 5 6
SamR
  • 8,826
  • 3
  • 11
  • 33
  • Thank you, the list approach completely solves my problem. I must ask though: why is eval(parse()) not recommended? Simply because it's an overly complicated solution, or something like prone to bugs / computationally inefficient? – Peter Z Oct 11 '22 at 10:01
  • Basically because it's confusing to read and hard to debug (particularly if you're using a debugger in your IDE or the `debug()` function) and also sometimes because of security concerns - see [here](https://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse) for more. – SamR Oct 11 '22 at 10:18