[R] Question about 'text' (add lm summary to a plot)

Gabor Grothendieck ggrothendieck at gmail.com
Fri Jul 22 18:49:42 CEST 2005


On 7/22/05, Dan Bolser <dmb at mrc-dunn.cam.ac.uk> wrote:
> On Fri, 22 Jul 2005, Gabor Grothendieck wrote:
> 
> >Try as.expression(bquote(...whatever...))
> 
> Sob, wimper, etc.
> 
> 
> my.slope.1 <-   3.22
> my.slope.2 <-   0.13
> my.inter.1 <- -10.66
> my.inter.2 <-   1.96
> my.Rsqua.1 <-   0.97
> 
> 
> 
> text(2,5,
>  paste("Slope:  ",
>        as.expression(bquote(.(my.slope.1)%+-%.(my.slope.2)))))

Thomas Lumley has already answered with a solution but I 
thought I would address this specific construct.  The problem is
that the above converts it back to character.  You want to put
everything in the bquote so it stays an expression:

my.slope.1 <-   3.22
my.slope.2 <-   0.13

plot(1:5)
text(2,5, as.expression(bquote(Slope: .(my.slope.1)%+-%.(my.slope.2))))






> 
> 
> That puts the text and variable together, but not the symbol, which is
> printed as '%+-%'
> 
> The following is nearly right, but wrong enough it makes my first attempt
> look reasonable...
> 
> 
> # Create the initial plot as per Christoph's post
> plot(1:5, 1:5, type = "n")
> 
> legend(x=1,
>       y=4.5,
>       bg='white',
>       ncol=3,
>       c("Slope","Intercept",expression(R^2),
>         ":",":",":",
>         bquote( .(my.slope.1)%+-%.(my.slope.2)),
>         bquote( .(my.inter.1)%+-%.(my.inter.2)),
>         my.Rsqua.1
>         )
>       )
> 
> Anyone got any ideas on how to fix the above?
> 
> Namely 1) right align numbers, 2) remove excessive white space.
> 
> I like the above because it dosn't require me to calculate exactly where
> to put each piece of text.
> 
> 
> I just want to annotate a plot :(
> 
> 
> 
> >
> >
> >On 7/22/05, Dan Bolser <dmb at mrc-dunn.cam.ac.uk> wrote:
> >> On Thu, 21 Jul 2005, Marc Schwartz (via MN) wrote:
> >>
> >> >[Note: the initial posts have been re-arranged to attempt to maintain
> >> >the flow from top to bottom]
> >> >
> >> >> >Dan Bolser writes:
> >> >> > >
> >> >> > > I would like to annotate my plot with a little box containing the slope,
> >> >> > > intercept and R^2 of a lm on the data.
> >> >> > >
> >> >> > > I would like it to look like...
> >> >> > >
> >> >> > >  +----------------------------+
> >> >> > >  | Slope     :   3.45 +- 0.34 |
> >> >> > >  | Intercept : -10.43 +- 1.42 |
> >> >> > >  | R^2       :   0.78         |
> >> >> > >  +----------------------------+
> >> >> > >
> >> >> > > However I can't make anything this neat, and I can't find out how to
> >> >> > > combine this with symbols for R^2 / +- (plus minus).
> >> >> > >
> >> >> > > Below is my best attempt (which is franky quite pour). Can anyone
> >> >> > > improve on the below?
> >> >> > >
> >> >> > > Specifically,
> >> >> > >
> >> >> > > aligned text and numbers,
> >> >> > > aligned decimal places,
> >> >> > > symbol for R^2 in the text (expression(R^2) seems to fail with
> >> >> > > 'paste') and +-
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Cheers,
> >> >> > > Dan.
> >> >> > >
> >> >> > >
> >> >> > > dat.lm <- lm(dat$AVG_CH_PAIRS ~ dat$CHAINS)
> >> >> > >
> >> >> > > abline(coef(dat.lm),lty=2,lwd=1.5)
> >> >> > >
> >> >> > >
> >> >> > > dat.lm.sum <- summary(dat.lm)
> >> >> > > dat.lm.sum
> >> >> > >
> >> >> > > attributes(dat.lm.sum)
> >> >> > >
> >> >> > > my.text.1 <-
> >> >> > >   paste("Slope : ",     round(dat.lm.sum$coefficients[2],2),
> >> >> > >         "+/-",          round(dat.lm.sum$coefficients[4],2))
> >> >> > >
> >> >> > > my.text.2 <-
> >> >> > >   paste("Intercept : ", round(dat.lm.sum$coefficients[1],2),
> >> >> > >         "+/-",          round(dat.lm.sum$coefficients[3],2))
> >> >> > >
> >> >> > > my.text.3 <-
> >> >> > >   paste("R^2 : ",       round(dat.lm.sum$r.squared,2))
> >> >> > >
> >> >> > > my.text.1
> >> >> > > my.text.2
> >> >> > > my.text.3
> >> >> > >
> >> >> > >
> >> >> > > ## Add legend
> >> >> > > text(x=3,
> >> >> > >      y=300,
> >> >> > >      paste(my.text.1,
> >> >> > >            my.text.2,
> >> >> > >            my.text.3,
> >> >> > >            sep="\n"),
> >> >> > >      adj=c(0,0),
> >> >> > >      cex=1
> >> >
> >> >
> >> >> On Thu, 21 Jul 2005, Christoph Buser wrote:
> >> >>
> >> >> >Dear Dan
> >> >> >
> >> >> >I can only help you with your third problem, expression and
> >> >> >paste. You can use:
> >> >> >
> >> >> >plot(1:5,1:5, type = "n")
> >> >> >text(2,4,expression(paste("Slope : ", 3.45%+-%0.34, sep = "")), pos = 4)
> >> >> >text(2,3.8,expression(paste("Intercept : ", -10.43%+-%1.42)), pos = 4)
> >> >> >text(2,3.6,expression(paste(R^2,": ", "0.78", sep = "")), pos = 4)
> >> >
> >> >> >I do not have an elegant solution for the alignment.
> >> >
> >> >
> >> >On Thu, 2005-07-21 at 19:55 +0100, Dan Bolser wrote:
> >> >> Cheers for this.
> >> >>
> >> >> I was trying to get it to work, but the problem is that I need to replace
> >> >> the values above with variables, from the following code...
> >> >>
> >> >>
> >> >> dat.lm <- lm(dat$AVG_CH_PAIRS ~ dat$CHAINS)
> >> >> dat.lm.sum <- summary(dat.lm)
> >> >>
> >> >> my.slope.1 <- round(dat.lm.sum$coefficients[2],2)
> >> >> my.slope.2 <- round(dat.lm.sum$coefficients[4],2)
> >> >>
> >> >> my.inter.1 <- round(dat.lm.sum$coefficients[1],2)
> >> >> my.inter.2 <- round(dat.lm.sum$coefficients[3],2)
> >> >>
> >> >> my.Rsqua.1 <- round(dat.lm.sum$r.squared,2)
> >> >>
> >> >>
> >> >> Anything I try results in either the words 'paste("Slope:", my.slope.1,
> >> >> %+-%my.slope.2,sep="")' being written to the plot, or just
> >> >> 'my.slope.1+-my.slope2' (where the +- is correctly written).
> >> >>
> >> >> I want to script it up and write all three lines to the plot with
> >> >> 'sep="\n"', rather than deciding three different heights.
> >> >
> >> >
> >> >> Thanks very much for what you gave, its a good start for me to figure out
> >> >> how I am supposed to be telling R what to do!
> >> >>
> >> >> Any way to just get fixed width fonts with text? (for the alignment
> >> >> problem)
> >> >
> >> >
> >> >Dan,
> >> >
> >> >Here is one approach. It may not be the best, but it gets the job done.
> >> >You can certainly take this and encapsulate it in a function to automate
> >> >the text/box placement and to pass values as arguments.
> >> >
> >> >A couple of quick concepts:
> >> >
> >> >1. As far as I know, plotmath cannot do multiple lines, so each line in
> >> >your box needs to be done separately.
> >> >
> >> >2. The horizontal alignment is a bit problematic when using expression()
> >> >or bquote() since I don't believe that multiple spaces are honored as
> >> >such after parsing. Thus I break up each component (label, ":" and
> >> >values) into separate text() calls. The labels are left justified.
> >> >
> >> >3. The alignment for the numeric values are done with right
> >> >justification. So, as long as you use a consistent number of decimals in
> >> >the value outputs (2 here), you should be OK. This means you might need
> >> >to use formatC() or sprintf() to control the numeric output values on
> >> >either side of the +/- sign.
> >> >
> >> >4. In the variable replacement, note the use of substitute() and the
> >> >list of x and y arguments as replacement values in the expressions.
> >> >
> >> >
> >> >
> >> ># Set your values
> >> >my.slope.1 <- 3.45
> >> >my.slope.2 <- 0.34
> >> >
> >> >my.inter.1 <- -10.43
> >> >my.inter.2 <- 1.42
> >> >
> >> >my.Rsqua <- 0.78
> >> >
> >> >
> >> ># Create the initial plot as per Christoph's post
> >> >plot(1:5, 1:5, type = "n")
> >> >
> >> >
> >> >#-------------------------------------
> >> ># Do the Slope
> >> >#-------------------------------------
> >> >
> >> >text(1, 4.5,  "Slope", pos = 4)
> >> >text(2, 4.5, ":")
> >> >text(3, 4.5, substitute(x %+-% y,
> >> >                        list(x = my.slope.1,
> >> >                             y = my.slope.2)),
> >> >     pos = 2)
> >> >
> >> >
> >> >#-------------------------------------
> >> ># Do the Intercept
> >> >#-------------------------------------
> >> >
> >> >text(1, 4.25, "Intercept", pos = 4)
> >> >text(2, 4.25, ":")
> >> >text(3, 4.25, substitute(x %+-% y,
> >> >                         list(x = my.inter.1,
> >> >                              y = my.inter.2)),
> >> >     pos = 2)
> >> >
> >> >
> >> >#-------------------------------------
> >> ># Do R^2
> >> >#-------------------------------------
> >> >
> >> >text(1, 4.0, expression(R^2), pos = 4)
> >> >text(2, 4.0, ":")
> >> >text(3, 4.0,  substitute(x, list(x = my.Rsqua)),
> >> >     pos = 2)
> >> >
> >> >
> >> >#-------------------------------------
> >> ># Do the Box
> >> >#-------------------------------------
> >> >
> >> >rect(1, 3.75, 3, 4.75)
> >> >
> >> >
> >> >You can adjust the x,y coordinates for the various text elements as you
> >> >may require and can also calculate them based upon the xlim, ylim of
> >> >your actual plot. You can also modify the 'cex' argument to text() for
> >> >adjusting the sizes of the fonts in use.
> >>
> >>
> >> I have been trying many different combinations of the suggestions so
> >> far...
> >>
> >> bquote, substitute, expression, paste, etc.
> >>
> >> Also I was trying to use the 'expression' part of the 'legend' function to
> >> make thing easier (make new lines, make columns, make rectangles)...
> >>
> >> So far all in vain.
> >>
> >> I am sure a fairly neat solution is possible using 'legend' and
> >> 'expression', but I cant get a legend which contains a variable
> >> substituted value *and* a special symbol.
> >>
> >> Can anyone show me an example of this simple step, and then I can try to
> >> build on that.
> >>
> >>
> >> Thanks all for suggestions, its one of those 'it seems so easy' problems
> >> (for me).
> >>
> >> P.S. Whats with the documentation for bquote?
> >>
> >>
> >>
> >> >BTW, to use a monospaced font, you can set par(family = "mono").
> >> >See ?par for more information.
> >> >
> >> >HTH,
> >> >
> >> >Marc Schwartz
> >> >
> >> >
> >>
> >> ______________________________________________
> >> R-help at stat.math.ethz.ch mailing list
> >> https://stat.ethz.ch/mailman/listinfo/r-help
> >> PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
> >>
> >
> 
>




More information about the R-help mailing list