[R-sig-ME] simulate() fails for poisson lmer fits
William Valdar
valdar at well.ox.ac.uk
Thu Aug 2 14:11:32 CEST 2007
That works perfectly, thanks very much!
It's also considerably faster than the hack fix I wrote in the early hours
of this morning (included below only for interest and as a warning to
others).
Will
---hack---
rnorm.factor <- function(g, sd=1, mean=0)
# generate rnorm for a simple "batch" effect
{
g <- as.factor(g)[drop=TRUE]
x.g <- rnorm( nlevels(g), sd=sd, mean=mean )
return (x.g[g])
}
simulate.lmer.hack <- function(fit, nsim=1, seed=NULL, ...)
# simulate from fitted lmer obj with simple random intercepts
{
if (!is.null(seed)) set.seed(seed)
n <- length(fitted(fit))
fixed.linpreds <- model.matrix(attr(fit, "terms"),
data=attr(fit, "frame")) %*% fixef(fit)
ymat <- matrix(NA, nrow=n, ncol=nsim)
for (s in 1:nsim)
{
random.linpreds <- rep(0, length(n))
vc <- VarCorr(fit)
for (i in 1:length(vc))
{
random.sd <- sqrt(vc[[i]][1])
random.data <- attr(fit, "flist")[[i]]
random.linpreds <- random.linpreds +
rnorm.factor(random.data, sd=random.sd, mean=0)
}
# make canonical param
theta <- fixed.linpreds + random.linpreds
if (is.null(attr(fit, "family")))
{
scale <- attr(vc, "sc")
ymat[,s] <- rnorm(n, theta, scale)
}
else if ("poisson" == attr(fit, "family")$family)
{
ymat[,s] <- rpois(n, attr(fit, "family")$linkinv(theta))
}
}
as.data.frame(ymat)
}
counts <- data.frame(
count = c(8, 3, 0, 3, 0, 9, 0, 11, 4, 7, 0, 0, 0, 4, 3, 6, 3,
15, 11, 9),
batch = c(3.1, 3.1, 3.1, 3.3, 3.3, 3.3, 3.2, 3.12, 3.8, 3.11,
3.4, 3.4, 3.4, 3.4, 3.5, 3.5, 3.5, 3.5, 3.6, 3.6),
weight = c(324.4, 372.5, 352.7, 379.6, 388.1, 431, 448.4, 377.3,
376.5, 358.4, 356, 351.4, 350.8, 332.1, 334.5, 392, 370.5,
409.7, 375, 318.5))
fit.poisson <- lmer(count ~ weight + (1|batch), family=poisson,
data=counts)
simulate.lmer.hack(fit.poisson)
On Thu, 2 Aug 2007, Martin Maechler wrote:
> Hi,
>>>>>> "WV" == William Valdar <valdar at well.ox.ac.uk>
>>>>>> on Wed, 1 Aug 2007 18:49:58 +0100 (BST) writes:
>
> WV> Hello, I wish to simulate() from a fitted Poisson
> WV> GLMM. Both lmer() and lmer2() from lme4 (version info at
> WV> the bottom) fail, apparently due to bugs. Here's a test
> WV> case:
>
> counts <- data.frame(
> count = c(8, 3, 0, 3, 0, 9, 0, 11, 4, 7, 0, 0, 0, 4, 3, 6, 3,
> 15, 11, 9),
> batch = c(3.1, 3.1, 3.1, 3.3, 3.3, 3.3, 3.2, 3.12, 3.8, 3.11,
> 3.4, 3.4, 3.4, 3.4, 3.5, 3.5, 3.5, 3.5, 3.6, 3.6),
> weight = c(324.4, 372.5, 352.7, 379.6, 388.1, 431, 448.4, 377.3,
> 376.5, 358.4, 356, 351.4, 350.8, 332.1, 334.5, 392, 370.5,
> 409.7, 375, 318.5))
>
> fit <- lmer(count ~ weight + (1|batch), family=poisson, data=counts)
>
> MM, that works fine, but
>
> simulate(fit)
>
> gives what you say:
>
> WV> # Error: inherits(object, "lmer") is not TRUE
>
> and that's indeed a bug in the simulate method:
>
> Using inherits(object, "lmer") is wrong and should be
> replaced by is(object, "lmer") .
>
> Instead of waiting for the next version of lme4,
> I think the following should work for you:
>
>
> setMethod("simulate", signature(object = "mer"),
> function(object, nsim = 1, seed = NULL, ...)
> {
> if(!exists(".Random.seed", envir = .GlobalEnv))
> runif(1) # initialize the RNG if necessary
> if(is.null(seed))
> RNGstate <- .Random.seed
> else {
> R.seed <- .Random.seed
> set.seed(seed)
> RNGstate <- structure(seed, kind = as.list(RNGkind()))
> on.exit(assign(".Random.seed", R.seed, envir = .GlobalEnv))
> }
>
> stopifnot((nsim <- as.integer(nsim[1])) > 0, is(object, "lmer"))
> ## similate the linear predictors
> lpred <- .Call(lme4:::mer_simulate, object, nsim)
> sc <- abs(object at devComp[8])
>
> ## add fixed-effects contribution and per-observation noise term
> lpred <- as.data.frame(lpred + drop(object at X %*% fixef(object)) +
> rnorm(prod(dim(lpred)), sd = sc))
> ## save the seed
> attr(lpred, "seed") <- RNGstate
> lpred
> })
>
>
> at least it fixes the problem for me.
>
>
> WV> fit <- lmer2(count ~ weight + (1|batch), family=poisson, data=counts)
> WV> simulate(fit)
> WV> # CHOLMOD error: X and/or Y have wrong dimensions
> WV> # Error in crossprod(object at ZXyt, c(unlist(lapply(seq_along(re),
> WV> # function(k) (t(cholL[[k]]) %*% :
> WV> # Cholmod error 'X and/or Y have wrong dimensions' at
> WV> # file:../MatrixOps/cholmod_sdmult.c, line 90
>
> I can confirm that error and I agree that it is a bug,
> well at least in the error message :-)
>
> BTW, also summary(fit) gives an error.
> {which is caused by vcov(fit) getting 0 x 0 matrix }
>
> But then, lmer2() is in beta testing,
> so thanks a lot for your nicely reproducible example.
>
>
> Note that your data set has only one observation for some batch
> levels which may be deemed to give problems,
> but in fact that's not the problem here at all.
>
> Regards,
> Martin Maechler, ETH Zurich
>
>
> WV> Is there a quick fix for either of these two? Otherwise, is there an
> WV> alternative (I've checked objects produced by nlme, glmmPQL, GLMMGibbs
> WV> with no luck)? I am using lme4 0.99875-6 version R 2.5.1 on Windows XP.
>
> WV> Many thanks,
>
> WV> Will
>
> WV> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> WV> Dr William Valdar ++44 (0)1865 287 589
> WV> Wellcome Trust Centre valdar at well.ox.ac.uk
> WV> for Human Genetics, Oxford www.well.ox.ac.uk/~valdar
>
>
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Dr William Valdar ++44 (0)1865 287 589
Wellcome Trust Centre valdar at well.ox.ac.uk
for Human Genetics, Oxford www.well.ox.ac.uk/~valdar
More information about the R-sig-mixed-models
mailing list