Hi,
In case this is helpful for anyone, I think I've coded a satisfactory
function answering my problem (of handling formulas containing 1-level
factors) by hacking liberally at the model.matrix code to remove any
model terms for which the contrast fails. As it's a problem I've come
across a lot (since my data frames have factors and lots of missing
values), adding support for 1-level factors might be a nice item for
the R Wishlist. I suppose a key question is, does anyone ever _want_
to see the error "contrasts can be applied only to factors with 2 or
more levels", or should the contrasts function just add a column of
all zeros (or ones) to the design matrix and let the modelling
functions handle that the same way it does any other zero-variance
term?

Anyway, my function below:

lmresid <- function(formula, data) {
    mf <- model.frame(formula, data=data, na.action=na.exclude)
    omit <- attr(mf, "na.action")
    t <- terms(mf)
    contr.funs <- as.character(getOption("contrasts"))
    namD <- names(mf)
    for (i in namD) if (is.character(mf[[i]]))
        mf[[i]] <- factor(mf[[i]])
    isF <- vapply(mf, function(x) is.factor(x) || is.logical(x), NA)
    isF[1] <- FALSE
    isOF <- vapply(mf, is.ordered, NA)
    for (nn in namD[isF])
        if (is.null(attr(mf[[nn]], "contrasts"))) {
            noCntr <- try(contrasts(mf[[nn]]) <- contr.funs[1 +
isOF[nn]], silent=TRUE)
            if (inherits(noCntr, "try-error")) {       # Remove term
from model on error
                mf[[nn]] <- NULL
                t <- terms(update(t, as.formula(paste("~ . -", nn))), data=mf)
            }
        }
    ans <- .External2(stats:::C_modelmatrix, t, mf)
    r   <- .lm.fit(ans, mf[[1]])$residual
    stats:::naresid.exclude(omit, r)
}

## Note that lmresid now returns the same values as resid with the
## 1-level factor removed.
df <- data.frame(y=c(0,2,4,6,8), x1=c(1,1,2,2,NA),
x2=factor(c("A","A","A","A","B")))
lmresid(y~x1+x2, data=df)
resid(lm(y~x1, data=df, na.action=na.exclude))

--Robert

PS, Peter, wasn't sure if you also meant to add comments, but they
didn't come through.


On Fri, Mar 11, 2016 at 3:40 AM, peter dalgaard <pda...@gmail.com> wrote:
>
>> On 11 Mar 2016, at 02:03 , Robert McGehee <rmcge...@gmail.com> wrote:
>>
>>> df <- data.frame(y=c(0,2,4,6,8), x1=c(1,1,2,2,NA),
>> x2=factor(c("A","A","A","A","B")))
>>> resid(lm(y~x1+x2, data=df, na.action=na.exclude)
>
> --
> Peter Dalgaard, Professor,
> Center for Statistics, Copenhagen Business School
> Solbjerg Plads 3, 2000 Frederiksberg, Denmark
> Phone: (+45)38153501
> Office: A 4.23
> Email: pd....@cbs.dk  Priv: pda...@gmail.com
>
>
>
>
>
>
>
>
>

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to