theforestecologist
theforestecologist

Reputation: 4917

Inserting changing for-loop variable into model formula

I have the following function:

sincos.chooser <- function(mod,min,max) {
  my.aic.sincos <- matrix(NA, ncol=2, nrow=max)
  for(k in c(min:max)) { 
    sincos.update <- update(mod, .~. + I(cos(2*pi/k*(order.ID))) + I(sin(2*pi/k*(order.ID))))
    my.aic.sincos[k,] <- c(k,AIC(sincos.update))
  }
  my.aic.sincos
}

But when I run the function I get the following error:

Error in get("k") : object 'k' not found

How do I make the changing variable k recognized in the update function of my loop?

I assume the issue here is that the update function assumes "k" is a column name in my data.frame and therefore cannot find the object. I want it to view "k" as a variable, not as a parameter name.


Update: I tried using get('k') in place of just "k." This works if I move the update function outside of my "sincos.chooser" function, but creates the same error as above when used inside my function.


For those that want to see my data & model:

Original model:

gls(GDD ~ year + pdo, data = dat)

Format of my data:

> dat
    year month   temp.avg   ppt.avg       GDD   pdo  order.ID
1   1922     1  0.4935484 0.3535484  14.40737 -0.45         1
2   1923     2  4.3892857 0.4542857  56.03017 -1.51         2
3   1924     3  7.3032258 0.5435484 106.49244 -1.76         3
4   1925     4 12.8533333 0.2583333 239.07739 -1.71         4
5   1926     5 19.7903226 0.4667742 458.50000 -1.61         5
6   1927     6 24.2766667 0.3146667 578.30000 -1.11         6

Upvotes: 2

Views: 1445

Answers (2)

theforestecologist
theforestecologist

Reputation: 4917

There's a neater (or at least more generally applicable) way to do this: use substitute()

sincos.update <- update(mod3, substitute(.~. + I(cos(2*pi/i*(Plot))) + I(sin(2*pi/i*(Plot))),list(i = as.numeric(k))))

Or, in context to the question:

sincos.chooser <- function(mod,min,max) {
  my.aic.sincos <- matrix(NA, ncol=2, nrow=max)
  for(k in c(min:max)) { 

    sincos.update <- update(mod3, 
      substitute(
        .~. + I(cos(2*pi/i*(Plot))) + I(sin(2*pi/i*(Plot))),
        list(i = as.numeric(k))
      )
    )

    my.aic.sincos[k,] <- c(k,AIC(sincos.update))
  }
  my.aic.sincos
} 

This approach also works well when you try to recursively add variables (as column names from a data.frame) to a model:

#Set-up Data
  dat <- data.frame(Id = rep(1:5,3), X = runif(15), Y = runif(15), Var1 = runif(15), Var2 = runif(15))
  varnames <- names(dat)

#Use substitute() in function:    
  lapply(varnames[grep('Var',varnames)], function(x) 
    lm( substitute(Y ~ X + i, list(i = as.name(x))), data = dat)
  ) 

Upvotes: 1

theforestecologist
theforestecologist

Reputation: 4917

This cannot be the neatest way to make this work, but it is a solution:

Use formula and paste0:

sincos.update <- update(mod, formula(paste0('.~. + I(cos(2*pi/',k,'*(order.ID))) + I(sin(2*pi/',k,'*(order.ID)))')))

Upvotes: 1

Related Questions