From ripley at stats.ox.ac.uk  Tue Dec 19 05:19:13 2006
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Tue, 19 Dec 2006 04:19:13 +0000 (GMT)
Subject: [Rd] abline for intercept-only simple lm models (with and
 without offset)
In-Reply-To: <17798.31650.32450.409165@stat.math.ethz.ch>
References: <457B2DCE.8030807@telenet.be>
	<17789.23164.990822.30599@stat.math.ethz.ch>
	<4585B7FA.2010600@telenet.be>
	<17798.31650.32450.409165@stat.math.ethz.ch>
Message-ID: <Pine.LNX.4.64.0612190359050.13505@gannet.stats.ox.ac.uk>

The patch put in R-devel is broken and I have had to revert it. abline 
predates lm, and one can do things like (in the forecasting bundle)

> plot(sales,type="p")
> abline(lsfit(1:10,sales))
Error in terms.default(a) : no terms component

About 10 CRAN packages were affected.  What abline did is correct for 
lsfit.

If I understand the intention, any changes need to be conditional on 
inherits(a, "lm").

On Mon, 18 Dec 2006, Martin Maechler wrote:

>>>>>> "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
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

-- 
Brian D. Ripley,                  ripley at stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595



[Rd] abline for intercept-only simple lm models (with and without offset)
Prof Brian Ripley