Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run effect plot inside of a R function

Tags:

r

Update: Previous title was Is there any specific way to pass data frame as an argument to a function? but it was not right question according to brilliant guys here. Original post is below.

When I ran following function with somefunc(sleepstudy),

somefunc<-function (dataLme) 
{
 library(effects)
 library(lme4)

 fm8 <- lmer(Reaction ~ 1 + Days + (1 + Days|Subject), dataLme,
      REML = 0, verbose = TRUE)

 plot(effect("Days",fm8))
}

I got an error.

Error in plot(effect("Days", fm8)) : 
  error in evaluating the argument 'x' in selecting a method for function 'plot': Error in is.data.frame(data) : object 'dataLme' not found

But if I manually executed

library(effects)
library(lme4)
fm8 <- lmer(Reaction ~ 1 + Days + (1 + Days|Subject), sleepstudy,
    REML = 0, verbose = TRUE)
plot(effect("Days",fm8))

I didn't get any error.

I thought R passes by value meaning copying whole object content to the function argument. But it looks like I was not entirely right. Can anyone explain what is going on?

like image 897
Tae-Sung Shin Avatar asked Apr 08 '13 17:04

Tae-Sung Shin


2 Answers

A (hacky) workaround is to assign dataLme into the global environment, where effect() will be able to find it:

library(effects)
library(lme4)

somefunc <- function (dataLme) {
    ## Assign to a symbol that's unlikely to be in use in .GlobalEnv
    ## (and make sure this function cleans up after itself!)
    assign(".TeMpVaR", dataLme, envir=globalenv())
    on.exit(rm(.TeMpVaR, envir=globalenv()))

    fm8 <- lmer(Reaction ~ 1 + Days + (1 + Days|Subject), .TeMpVaR,
         REML = 0, verbose = TRUE)    
    plot(effect("Days",fm8))
}

somefunc(sleepstudy)
like image 72
Josh O'Brien Avatar answered Oct 12 '22 15:10

Josh O'Brien


This is only a partial answer, but I did want to document my testing procedure. I mainly wanted to show that the issue is particularly with the effects package rather than with the lme4 package (which I maintain, and which has encountered these sorts of problems as well: most such problems are fixed in the development version of lme4, but some persist in the stable version, installed as lme4.0 on my system ...)

library("effects")

showpkgs <- function() names(sessionInfo()$otherPkgs)
somefunc<-function (dataLme, pkg="nlme")  {
    require(pkg,character.only=TRUE)
    on.exit(detach(paste("package",pkg,sep=":"),unload=TRUE,character.only=TRUE))
    if (pkg=="nlme") {
        fm8 <- lme(Reaction ~ 1 + Days,random=~Days|Subject, dataLme)
    } else {
        fm8 <- lmer(Reaction ~ 1 + Days + (1 + Days|Subject), dataLme, REML = 0)
    }
    plot(effect("Days",fm8))
}

The error occurs whether we use stable lme4, development lme4, or the older nlme package

data("sleepstudy",package="lme4")
showpkgs()
somefunc(sleepstudy)  ## nlme
showpkgs()  ## warning about unloading nlme namespace due to glmmADMB dep. (??)
somefunc(sleepstudy,pkg="lme4.0")  ## lme4-stable
showpkgs()  ## failure to remove Matrix/warning message
somefunc(sleepstudy,pkg="lme4")    ## lme4-devel
showpkgs()  ## leaves RcppEigen, Rcpp loaded as well

I took a bit of a look at the effects package, and a simple universal fix is not immediately obvious. Changing the relevant eval(cl) lines to eval(cl,envir=environment(formula(mod))) works for development lme4, but not for stable lme4 or nlme ...

like image 31
Ben Bolker Avatar answered Oct 12 '22 14:10

Ben Bolker