20

Hi I'm trying to name variables using a for loop so I get dynamic names for my variables.

for (i in 1:nX) {
    paste("X",i, sep="")=datos[,i+1]
    next
}
Jaap
  • 81,064
  • 34
  • 182
  • 193
nopeva
  • 1,583
  • 5
  • 22
  • 38
  • 3
    Why are you trying to do that? Use the array instead. – nico Dec 29 '12 at 13:11
  • Hi, I have a data frame with long headers but would like to automatically set my own variables as X1, X2, etc so I can operate with them individually – nopeva Dec 29 '12 at 13:27
  • 6
    Why don't you just do `colNames(datos) <- paste("X", i, sep="")` then? Then you can access them with `datos$X1`, `datos$X2` etc – nico Dec 29 '12 at 13:29
  • Thanks nico that is a nice solution! – nopeva Dec 29 '12 at 13:38
  • 9
    This is faq 7.21, the most important part of that answer is the last part that says not to do this, use a list or environment. – Greg Snow Dec 29 '12 at 14:34
  • is there a canonical version of this "dynamically name variables" question that I can start using as a duplicate target? (The answers here are OK, but I'd prefer a question where at least one of the answers spells out the classic "use a list instead"/FAQ 7.21 logic ...) – Ben Bolker Jan 17 '21 at 00:58

2 Answers2

34

use assign as in:

x <- 1:10

for(i in seq_along(x)){
  assign(paste('X', i, sep=''), x[i])
}
Jilber Urbina
  • 58,147
  • 10
  • 114
  • 138
  • Hi David, why do you think is a bad idea? – nopeva Dec 29 '12 at 14:03
  • 2
    @user1228124 Experienced R programmers generally advise against using `assign` unless you are absolutely forced to. In this case, nico's suggestion of using `colnames<-` is safer, simpler, and easier to understand. – joran Dec 29 '12 at 14:36
  • plus one, this saved me time – yanes Dec 15 '15 at 20:32
12

It can be a good idea to use assign when there are many variables and they are looked up frequently. Lookup in an environment is faster than in vector or list. A separate environment for the data objects is a good idea.

Another idea is to use the hash package. It performs lookup as fast as environments, but is more comfortable to use.

datos <- rnorm(1:10)
library(hash)
h <- hash(paste("x", 1:10, sep=""), datos)
h[["x1"]]

Here is a timing comparision for 10000 vars that are looked up 10^5 times:

datos <- rnorm(1:10000)
lookup <- paste("x", sample.int(length(datos), 100000, replace=TRUE), sep="")

# method 1, takes 16s on my machine
names(datos) <- paste("x", seq_along(datos), sep="")
system.time(for(key in lookup) datos[[key]])

# method 2, takes 1.6s on my machine
library(hash)
h <- hash(paste("x", seq_along(datos), sep=""), datos)
system.time(for(key in lookup) h[[key]])

# method 3, takes 0.2s on my machine
e <- new.env()
for(i in seq_along(datos)){
  assign(paste('x', i, sep=''), datos[i], envir=e)
}
system.time(for(key in lookup) e[[key]])

However, the vectorized version of method 1 is the fastest, but is not always applicable

# method 4, takes 0.02s
names(datos) <- paste("x", seq_along(datos), sep="")
system.time(datos[lookup])
Karsten W.
  • 17,826
  • 11
  • 69
  • 103