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

From: Marc Schwartz (via MN) <mschwartz_at_mn.rr.com>
Date: Fri 22 Jul 2005 - 07:26:35 EST

[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.

BTW, to use a monospaced font, you can set par(family = "mono"). See ?par for more information.

HTH, Marc Schwartz



R-help@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 Received on Fri Jul 22 07:33:09 2005

This archive was generated by hypermail 2.1.8 : Fri 03 Mar 2006 - 03:33:55 EST