Fabio Marroni Fabio Marroni - 2 months ago 6
R Question

Boxplot error with a substitute command that works fine with hist() and plot()

I am asking your help to solve the following issue (and to help me understand the reasons the may have generated it).

I was trying to paste in a title of a boxplot some normal text, a symbol and the value of a variable.

I found on this website a simple way to do that, exemplified with some fake data and an histogram.

x_mean <- 1.5
x_sd <- 1.2
hist(rnorm(100, x_mean, x_sd),
main = substitute(
paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
list(m = x_mean, s2 = x_sd^2)
)
)


I liked it very much, so I tried, and I got the result I was expecting. Hist with title

I tried to to the same with plot and again, it was ok.
Plot with title

I tried to do the same with a boxplot

x_mean <- 1.5
x_sd <- 1.2
boxplot(rnorm(100, x_mean, x_sd),
main = substitute(
paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
list(m = x_mean, s2 = x_sd^2)
)
)


And I got the error:

Error in paste(X[i], " ~ N(", mu, "=", 1.5, ", ", sigma^2, "=", 1.44, :
object 'X' not found


Why?

What should I do to get the same behavior in boxplot?

Answer

The difference between plot/hist and boxplot seems to be that main is passed directly inside plot(..., main=) but boxplot eventually goes through bxp which uses do.call('title', list(main = ...) to plot this text:

If you use title manually, it works:

x_mean <- 1.5
x_sd <- 1.2
boxplot(rnorm(100, x_mean, x_sd))
title(main = substitute(
  paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
  list(m = x_mean, s2 = x_sd^2)
))

boxplot and bxp do this which gives an error

boxplot(rnorm(100, x_mean, x_sd))
do.call('title', list(main = substitute(
  paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
  list(m = x_mean, s2 = x_sd^2)
)))
# Error in paste(X[i], " ~ N(", mu, "=", 1.5, ", ", sigma^2, "=", 1.44,  : 
#   object 'X' not found

You can do this by hand just fine:

bxp(list(stats = matrix(1, 5), n = 1))
title(main = substitute(
  paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
  list(m = x_mean, s2 = x_sd^2)
))

Or if bxp used alist (instead of list) so that the X wouldn't attempt to be evaluated:

bxp(list(stats = matrix(1, 5), n = 1))
do.call('title', alist(main = substitute(
  paste(X[i], " ~ N(", mu, "=", m, ", ", sigma^2, "=", s2, ")"),
  list(m = x_mean, s2 = x_sd^2)))
  )
Comments