R Passing linear model to another function inside a function
Asked Answered
P

3

6

I am trying to find the optimal "lambda" parameter for the Box-Cox transformation.

I am using the implementation from the MASS package, so I only need to create the model and extract the lambda.

Here is the code for the function:

library(MASS)

find_lambda <- function(x) {
  # Function to find the best lambda for the Box-Cox transform

  my_tmp <- data.frame(x = x) # Create a temporary data frame, to use it with the lm
  str(my_tmp) # Gives the expected output

  the_lm <- lm(x ~ 1, data = my_tmp) # Creates the linear model, no error here
  print(summary(the_lm)) # Prints the summary, as expected

  out <- boxcox(the_lm, plotit=FALSE) # Gives the error

  best_lambda <- out$x[which.max(out$y)] # Extracting the best fitting lambda
  return(best_lambda)
}

find_lambda(runif(100))

It gives the following error:

Error in is.data.frame(data) : object 'my_tmp' not found 

The interesting thing is that the very same code is working outside the function. In other words, for some reason, the boxcox function from the MASS package is looking for the variable in the global environment.

I don't really understand, what exactly is going on... Do you have any ideas?

P.S. I do not provide a software/hardware specification, since this error was sucessfully replicated on a number of my friends' laptops.

P.P.S. I have found the way to solve the initial problem in the forecast package, but I still would like to know, why this code is not working.

Passover answered 27/9, 2016 at 15:17 Comment(0)
W
0

boxcox cannot find your data. This maybe because of some scoping issue.
You can feed data in to boxcox function.

find_lambda <- function(x) {
  # Function to find the best lambda for the Box-Cox transform

  my_tmp <- data.frame(x = x) # Create a temporary data frame, to use it with the lm
  str(my_tmp) # Gives the expected output

  the_lm <- lm(x ~ 1, data = my_tmp) # Creates the linear model, no error here
  print(summary(the_lm)) # Prints the summary, as expected

  out <- boxcox(the_lm, plotit=FALSE, data = my_tmp) # feed data in here

  best_lambda <- out$x[which.max(out$y)] # Extracting the best fitting lambda
  return(best_lambda)
}

find_lambda(runif(100))
Whig answered 27/9, 2016 at 15:30 Comment(0)
F
6

Sometimes user contributed packages don't always do a great job tracking the environments where calls were executed when manipulating functions calls. The quickest fix for you would be to change the line from

the_lm <- lm(x ~ 1, data = my_tmp)

to

the_lm <- lm(x ~ 1, data = my_tmp, y=True, qr=True)

Because if the y and qr are not requested from the lm call, the boxcox function tries to re-run lm with those parameters via an update call and things get mucked up inside a function scope.

Fraktur answered 27/9, 2016 at 15:27 Comment(0)
I
1

Why don't let box-cox do the fitting?

find_lambda <- function(x) {
  # Function to find the best lambda for the Box-Cox transform

  my_tmp <- data.frame(x = x) # Create a temporary data frame, to use it with the lm

  out <- boxcox(x ~ 1, data = my_tmp, plotit=FALSE) # Gives the error

  best_lambda <- out$x[which.max(out$y)] # Extracting the best fitting lambda
  return(best_lambda)
}

I think your scoping issue is with update.default which calls eval(call, parent.frame()) and my_tmp doesn't exist in the boxcox environment. Please correct me if I'm wrong on this.

Ineslta answered 27/9, 2016 at 15:34 Comment(0)
W
0

boxcox cannot find your data. This maybe because of some scoping issue.
You can feed data in to boxcox function.

find_lambda <- function(x) {
  # Function to find the best lambda for the Box-Cox transform

  my_tmp <- data.frame(x = x) # Create a temporary data frame, to use it with the lm
  str(my_tmp) # Gives the expected output

  the_lm <- lm(x ~ 1, data = my_tmp) # Creates the linear model, no error here
  print(summary(the_lm)) # Prints the summary, as expected

  out <- boxcox(the_lm, plotit=FALSE, data = my_tmp) # feed data in here

  best_lambda <- out$x[which.max(out$y)] # Extracting the best fitting lambda
  return(best_lambda)
}

find_lambda(runif(100))
Whig answered 27/9, 2016 at 15:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.