Putting variable names into a model automatically (created 2010-09-20, updated 2011-12-02).

This page is moving to a new website.

I always have trouble with including a changing variable name into a sequence of statistical models in R, so when someone wrote about it on the R-Help list, I thought I should try some of the suggestions and then write them down here so I don't forget.

Here's the problem. If you run models inside a loop, the information about models is not properly documented as part of the output. There is a small data set on house prices that can help illustrate this problem. Here are the first five rows of the data set.

> housing[1:5,]
  sqft age feats nec cust cor  price
1 2650  13     7   1    1   0 205000
2 2600  NA     4   1    1   0 208000
3 2664   6     5   1    1   0 215000
4 2921   3     6   1    1   0 215000
5 2580   4     4   1    1   0 199900

The first three variables are the square footage, age, and the number of special features of the house. The next three variables are indicators for whether the house is in the northeast corner of the city, whether it is a custom built house, and whether it is on a corner lot. The last variable is the sales price of the house. You might be interested in what variables predict sales price. Part of the preliminary analysis would be to look at simple univariate regression before fitting a more complex model. You could do this inside a loop, but when you do, the information about the individual variables is not carried along with the output. For example, this simple loop

for (i in 1:6) {print(coef(lm(price~housing[,i])))}

produces the following:

 (Intercept) housing[, i]
  4781.93066     61.36668
 (Intercept) housing[, i]
116847.00710    -24.75735
 (Intercept) housing[, i]
    66117.42     11375.94
 (Intercept) housing[, i]
    97282.05     13487.18
 (Intercept) housing[, i]
    94752.22     49925.56
 (Intercept) housing[, i]
  107718.947    -7687.129

The same problem occurs if you work with a function:

univ.coef <- function(dv,iv) {coef(lm(dv~iv))}
univ.coef(price,sqft)

which produces the following output

(Intercept)      iv
4781.93066 61.36668

Inside a loop, you can paste the model together.

for (i in 1:6) {
 tmp.formula <- as.formula(paste("price ~",names(housing)[i]))
 print(coef(lm(tmp.formula)))

}

which produces the following output

 (Intercept)      sqft
 4781.93066   61.36668
 (Intercept)       age
116847.00710 -24.75735
 (Intercept)     feats
    66117.42  11375.94
 (Intercept)       nec
    97282.05  13487.18
 (Intercept)      cust
    94752.22  49925.56
 (Intercept)       cor
  107718.947 -7687.129

This also works within a function, but you have to place your variable names in quotes.

univ.coef <- function(dvname,ivname) {
 tmp.formula <- as.formula(paste(dvname,"~",ivname))
 coef(lm(tmp.formula))
}
univ.coef("price","sqft")

which produces the following output

 (Intercept)      sqft
  4781.93066  61.36668

There was a similar question about functions. Suppose you have a character vector that represented the name of a function. You could convert that string to the actual function with the match.fun function. For example,

test.data <- 1:10
flist <- c("min","mean","max")
stat <- numeric(0)
for (i in 1:length(flist)) {
 fun <- match.fun(flist[i])
 stat[i] <- fun(test.data)
}
stat

produces the following output

[1] 1.0 5.5 10.0

Another more complicated approach is

test.data <- 1:10
flist <- c("min","mean","max")
stat <- numeric(0)
for (i in 1:length(flist)) {
 stat[i] <- eval(as.call(list(as.name(flist[i]), test.data)))
}
stat

which produces the following output

[1] 1.0 5.5 10.0

There's nothing wrong, though, with storing the functions themselves

test.data <- 1:10
flist <- c(min,mean,max)
stat <- numeric(0)
for (i in 1:length(flist)) {
 stat[i] <- flist[[i]](test.data)
}

stat

which produces the following output

[1] 1.0 5.5 10.0

You have to use double brackets because functions are combined as a list, not as a vector.

You might ask yourself, why go to all this trouble. One advantage of incorporating variables names from a list into a model or converting the string name of a function into the function itself is to that you can use the same string to create dimension names in a matrix, or incorporate those strings into the title of a graph. It also allows you to dynamically change the function list within the program.