[Rd] abline for intercept-only simple lm models (with and without offset)
Martin Maechler
maechler at stat.math.ethz.ch
Mon Dec 18 12:29:38 CET 2006
>>>>> "TobiasV" == Tobias Verbeke <tobias.verbeke at gmail.com>
>>>>> on Sun, 17 Dec 2006 22:34:50 +0100 writes:
TobiasV> Martin Maechler wrote:
>> Yes, I think all your propositions would be improvements.
>> OTOH, I don't think the improvements warrant a big
>> increase in code (complexity), nor do I think the
>> improvements are crucial for R's integrity.
>>
>> So... If you (our someone else) provides a patch
>> {against R-devel, as always} which keeps the code simple,
>> I'd strongly consider adding that to R.
>>
TobiasV> Dear Martin,
TobiasV> Thank you for the encouragement.
(maybe I shouldn't have done that, see below ...)
TobiasV> Please find a patch in attachment. As you will
TobiasV> see, I also added a warning for models with more
TobiasV> than 2 parameters.
the latter is a good idea [and I wonder if we should not even
signal an error ..]
but for the patch, see below.
TobiasV> Kind regards, Tobias
>>>>>>> "Tobias" == Tobias Verbeke
>>>>>>> <tobias.verbeke at telenet.be> on Sat, 09 Dec 2006
>>>>>>> 22:42:38 +0100 writes:
>>>>>>>
>>
Tobias> The abline function can be used to draw the
Tobias> regression line when one passes the lm object as an
Tobias> argument.
>>
Tobias> However, if it's an intercept-only model, it appears
Tobias> to use the intercept as the slope of the abline:
>>
Tobias> mod <- lm(dist ~ 1, data = cars)
Tobias> plot(dist ~ speed, data = cars)
Tobias> abline(reg = mod) # nothing appears
Tobias> This behaves as documented, but might catch
Tobias> someone. Would it be an improvement if this
Tobias> situation was detected so as to plot the appropriate
Tobias> horizontal line, i.e.
Tobias> abline(a = coef(mod), b = 0) ?
Tobias> Would it also be an improvement if for a model like
Tobias> mod2 <- lm(dist ~ 1 + offset(speed), data = cars)
Tobias> abline(reg = mod2) would be equivalent to
Tobias> abline(a = coef(mod2), b = 1) ?
Tobias> For models through the origin, the current function
Tobias> works fine, but one might even consider models
Tobias> through the origin and having the independent
Tobias> variable in an offset() to be fully fool-proof, i.e.
Tobias> abline(a = 0, b = 1)
Tobias> Kind regards, Tobias
Comments on your patch:
11,12c11,15
< temp <- as.vector(coef(a))
< if(length(temp) == 1) {
---
> tempa <- as.character(terms(a))
> coefa <- coef(a)
> if (length(coefa) > 2)
> warning("The abline function is meant to only plot the regression line for simple linear regression")
> if (length(grep("-[[:blank:]]?1", tempa))) {
14c17
< b <- temp
---
> b <- ifelse(length(grep("offset", tempa)), 1, coefa[1])
yet another misuse of ifelse() .... {as mentioned recently}.
Do note that if(Cond) A else B is
quite better than ifelse(Cond, A, B) in these scalar situations.
16,17c19,22
< a <- temp[1]
< b <- temp[2]
---
> a <- coefa[1]
> if (length(grep("offset", tempa))) b <- 1
> else if (length(coefa) >= 2) b <- coefa[2]
> else b <- 0
-- --
Hmm, grep()ing in as.character(terms(.))
is not really elegant though we could well live with that if ....
The real problems are
1. your offset dealing cannot work in generality
{and I should really have *dis*couraged you earlier on this}, since
a) lm() can have an 'offset' *argument* instead of or in
addition to the formula offset() component.
b) instead of offset(speed) one could have had offset(speed^2)
or offset(sqrt(dist)) or "anything".
Because of the above, it really doesn't make sense trying to
figure out offset corrections, at least not in abline()'s
code, I think.
2. To catch the "horizontal line" situation, it's also not
sufficient to grep for "-1" (basically); since, e.g.,
"0+" has been available to achieve the same and has actually
been preferred by some.
OTOH, there is a correct way of asking if there was an
intercept [attr(terms(.), "intercept")],
and I plan to use that in abline.
Regards,
Martin Maechler, ETH Zurich
More information about the R-devel
mailing list