R-alpha: 0.12 eval bug and other things

Thomas Lumley (thomas@biostat.washington.edu)
Fri, 20 Sep 1996 22:16:03 -0700 (PDT)


Date: Fri, 20 Sep 1996 22:16:03 -0700 (PDT)
From: Thomas Lumley <thomas@biostat.washington.edu>
To: R testers <r-testers@stat.math.ethz.ch>
Subject: R-alpha: 0.12 eval bug and other things
In-Reply-To: <Pine.SUN.3.91.960920165618.3386A-100000@zen>

1. Version 0.12 has an error in eval()

In the formal arguments it has sys.frame(sys.parent) rather than
sys.frame(sys.parent()).

2. A wonderful feature of R that I hadn't previously noticed is that the 
postscript() driver uses the same colours as the x11() driver. Anyone who 
has tried to print in colour from S-PLUS for Unix will appreciate this 
enormously.

3. The model.(data).frame fix is not quite right (my posted version was
similarly defective). It doesn't always correctly handle weight and subset
vectors. There are three problems to note.  The first is that weights must
be labelled "(weights)" for model.extract() to be able to find them. I
think this means that the naming can't (entirely) happen in
model.data.frame.  The second problem occurs when weight, offset or subset
parameters are names of terms in the data argument.  The current version
evaluates these arguments in the local environment, which fails. My fix,
which is not ideal, is to evaluate them in data if the argument is not
missing and if it doesn't exist in the local environment. This means that 
a global variable w clobbers a local variable data$w.  Finally, when 
there are weights or offsets in the model and data.frame is called 
explicitly the as.is=T qualifier is needed (as in model.data.frame). 
Otherwise multicolumn responses (such as for survival analysis or 
logistic regression) end up as multiple variables in the data frame.
eg
glm(cbind(yb,2-yb)~x,family=binomial(),offset=rep(0,length(yb))
gives
Error: no of items to replace is not a multiple of replacement length

My current version follows (you may want to change the na.action bit to 
na.action=na.fail, which is the standard R version):

thomas lumley
U Washington
------------------------------------------------
"model.frame" := function (formula, data, weights = NULL, offset = NULL, 
subset = NULL, na.action = eval(as.name(options("na.action")$na.action))) 
{
	if (!missing(data) || is.null(formula$model.frame)) {
		frame <- attr(terms(formula), "variables")
		if (missing(data)) {
			if (is.null(formula$call)) 
				data <- sys.frame(sys.parent())
			else data <- eval(formula$call$data, 
sys.frame(sys.parent()))
		}
		if (!(missing(subset) || exists("subset"))) 
			subset <- eval(match.call()$subset, data)
		if (!(missing(weights) || exists("weights"))) 
			weights <- eval(match.call()$weights, data)
		if (!(missing(offset) || exists("offset"))) 
			offset <- eval(match.call()$offset, data)
		if (is.null(weights) & is.null(offset)) 
			rval <- na.action(eval(frame, data)[subset, ,
 drop = FALSE])
		else if (is.null(offset)) 
			rval <- na.action(data.frame(eval(frame, data), 
.weights = weights, as.is = T)[subset, , drop = FALSE])
		else if (is.null(weights)) 
			rval <- na.action(data.frame(eval(frame, data), 
.offset = offset, as.is = T)[subset, , drop = FALSE])
		else rval <- na.action(data.frame(eval(frame, data),
 .weights = weights, .offset = offset, as.is = T)[subset, , drop = FALSE])
		attr(rval, "terms") <- terms(formula)
		xnames <- lapply(as.list(attr(terms(formula), "variables"))[-1],
 deparse)
		if (!missing(weights) && !is.null(weights)) 
			xnames <- c(xnames, "(weights)")
		if (!missing(offset) && !is.null(offset)) 
			xnames <- c(xnames, deparse(match.call()$offset))
		if (as.logical(length(xnames))) 
			names(rval) <- xnames
		rval
	}
	else formula$model.frame
}
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
r-testers mailing list -- To (un)subscribe, send
subscribe	or	unsubscribe
(in the "body", not the subject !)  To: r-testers-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-