Specify decimal places in r plot text?

elarry picture elarry · Mar 31, 2014 · Viewed 9.6k times · Source

I tried to format the label of my regression curve created in the base graphics system. Basically, this label extracts the slope, the intercept and the r-square values from variables. An example is as below:

plot(rnorm(10), type = "n", xlim = c(0, 100), ylim = c(0, 100))
text(x = 0, y = 100, adj = c(0, NA), bquote(paste(y == .(a) * x + .(b), ", R"^2 == .(r2))), cex = 0.7)

However, this generated a label that did not look very smart:

y = 1.159019x+-1.537708, R<sup>2</sup>=0.7924927

What I would like is to round the figures to the second decimal place, i.e.,

y = 1.16x-1.54, R<sup>2</sup>=0.79

I have looked it up in both help documents for text() and bquote() but did not find much useful information.

I have also tried to wrap the .(a), .(b) and .(r2) in format() with the parameter nsmall = 2, but it did not work.

Could someone kindly help me with this? Many thanks in advance!

ps. I think there is a hidden quest in my question. In the above example, b is negative. I know I could probably leave out the "+" operator in my expression to just use the negative sign of b to join my equation. However, what if I do not know the sign of b in advance? Is there a clever way of forming the label without checking this with an if() and then write two very slightly different versions of text()? Thanks again!

Answer

koekenbakker picture koekenbakker · Mar 31, 2014

For specifying the number of digits, use round(a, digits=2). However, you can also use sprintf to deal with both the number of digits and the + or - in your equation: e.q. %+3.2f, where % forces the + or - sign in the equation and 3.2f controls the number of digits, so this solves both your issues. I found a solution for the superscript problem in sprintf here: "B2 is the hex code for UTF-8 character = ^2 and \U is a control sequence that will call that character."

# data and regression
set.seed(1)
y = 1:10+rnorm(10)
x = 1:10
fit = lm(y~x)
b = coef(fit)[1]
a = coef(fit)[2]
r2 = summary(fit)$r.squared

# plot data and regression
plot(x, y)
abline(fit, col=2)

# add text to plot with legend() for convenient placement
legend('topleft', title='option 1', legend=sprintf("y = %3.2fx %+3.2f, R\UB2 = %3.2f", a, b, r2), bty='n', cex=0.7)

# if you prefer a pretty space between plus/minus and b:
if( b<0) {my_sign = ' - '; b = -b} else { my_sign= ' + '}
legend('bottomright', title='option 2', legend=sprintf("y = %3.2f x %s %3.2f, R\UB2 = %3.2f", a, my_sign, b, r2), bty='n', cex=0.7)

display equation on plot