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
  • 77,147
  • 31
  • 174
  • 185
nopeva
  • 1,561
  • 5
  • 22
  • 36
  • 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) – 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

33

use assign as in:

x <- 1:10

for(i in seq_along(x)){
  assign(paste('X', i, sep=''), x[i])
}
Jilber Urbina
  • 53,125
  • 10
  • 108
  • 134
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.
  • 16,858
  • 11
  • 64
  • 99