An lme4 user pointed out <https://github.com/lme4/lme4/issues/491> that
passing contrasts as a string or symbol to [g]lmer (which would work if
we were using `contrasts<-` to set contrasts on a factor variable) is
*silently ignored*. This goes back to model.matrix(), and seems bad
(this is a very easy mistake to make, because of the multitude of ways
to specify contrasts for factors in R  - e.g. options(contrasts=...);
setting contrasts on the specific factors; passing contrasts as a list
to the model function ... )

The relevant code is here:

https://github.com/wch/r-source/blob/trunk/src/library/stats/R/models.R#L578-L603

The following code shows the problem: a plain-vanilla model.matrix()
call with no contrasts argument, followed by two wrong contrasts
arguments, followed by a correct contrasts argument.

data(cbpp, package="lme4")
mf1 <- model.matrix(~period, data=cbpp)
mf2 <- model.matrix(~period, contrasts.arg="contr.sum", data=cbpp)
all.equal(mf1,mf2) ## TRUE
mf3 <- model.matrix(~period, contrasts.arg=contr.sum, data=cbpp)
all.equal(mf1,mf3)  ## TRUE
mf4 <- model.matrix(~period, contrasts.arg=list(period=contr.sum),
data=cbpp)
isTRUE(all.equal(mf1,mf4))  ## FALSE


  I've attached a potential patch for this, which is IMO the mildest
possible case (if contrasts.arg is non-NULL and not a list, it produces
a warning).  I haven't been able to test it because of some mysterious
issues I'm having with re-making R properly ...

  Thoughts?  Should I submit this as a bug report/patch?

  cheers
   Ben Bolker


Index: src/library/stats/R/models.R
===================================================================
--- src/library/stats/R/models.R	(revision 76140)
+++ src/library/stats/R/models.R	(working copy)
@@ -589,20 +589,23 @@
                 contrasts(data[[nn]]) <- contr.funs[1 + isOF[nn]]
         ## it might be safer to have numerical contrasts:
         ##	  get(contr.funs[1 + isOF[nn]])(nlevels(data[[nn]]))
-        if (!is.null(contrasts.arg) && is.list(contrasts.arg)) {
-            if (is.null(namC <- names(contrasts.arg)))
-                stop("invalid 'contrasts.arg' argument")
-            for (nn in namC) {
-                if (is.na(ni <- match(nn, namD)))
-                    warning(gettextf("variable '%s' is absent, its contrast will be ignored", nn),
-                            domain = NA)
-                else {
-                    ca <- contrasts.arg[[nn]]
-                    if(is.matrix(ca)) contrasts(data[[ni]], ncol(ca)) <- ca
-                    else contrasts(data[[ni]]) <- contrasts.arg[[nn]]
-                }
-            }
-        }
+        if (!is.null(contrasts.arg)) {
+            if (!is.list(contrasts.arg)) {
+                warning("non-list contrasts argument ignored")
+            } else {  ## contrasts.arg is a list
+                if (is.null(namC <- names(contrasts.arg)))
+                    stop("'contrasts.arg' argument must be named")
+                for (nn in namC) {
+                    if (is.na(ni <- match(nn, namD)))
+                        warning(gettextf("variable '%s' is absent, its contrast will be ignored", nn),
+                                domain = NA)
+                    else {
+                        ca <- contrasts.arg[[nn]]
+                        if(is.matrix(ca)) contrasts(data[[ni]], ncol(ca)) <- ca
+                        else contrasts(data[[ni]]) <- contrasts.arg[[nn]]
+                    }            }
+            } ## contrasts.arg is a list
+        } ## non-null contrasts.arg
     } else { #  no rhs terms ('~1', or '~0'): internal model.matrix needs some variable
 	isF <- FALSE
 	data[["x"]] <- raw(nrow(data))
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to