[R] lattice: how to "center" a subtitle?

Deepayan Sarkar deepayan.sarkar at gmail.com
Tue Apr 5 14:47:24 CEST 2011


On Tue, Apr 5, 2011 at 6:12 AM, David Scott <d.scott at auckland.ac.nz> wrote:

[...]

> I am not sure where I read it and I can't find it again, but my
> understanding is that expressions using bquote with lattice need to be
> enclosed in as.expression() to work. That is in contrast to what happens in
> base graphics.
>
> Here is a simple example.
>
> a <- 2
> plot(1:10, a*(1:10), main = bquote(alpha == .(a)))
> require(lattice)
> xyplot(a*(1:10)~ 1:10, main = bquote(alpha == .(a)))
> xyplot(a*(1:10)~ 1:10, main = as.expression(bquote(alpha == .(a))))
>
> Which produces:
>
>> a <- 2
>> plot(1:10, a*(1:10), main = bquote(alpha == .(a)))
>> require(lattice)
> Loading required package: lattice
>> xyplot(a*(1:10)~ 1:10, main = bquote(alpha == .(a)))
> Error in trellis.skeleton(formula = a * (1:10) ~ 1:10, cond = list(c(1L,  :
>  object 'alpha' not found
>> xyplot(a*(1:10)~ 1:10, main = as.expression(bquote(alpha == .(a))))
>
> Using expression() rather than as.expression() doesn't produce the desired
> affect. Try it yourself.
>
> As to why this is the case .....

Let's see: ?xyplot says

          'main': Typically a character string or expression describing
              the main title to be placed on top of each page. [...]

So, lattice is fairly explicit, by R standards, in requiring 'main' to
be "character" or "expression". On the other hand, ?title says

     The labels passed to 'title' can be character strings or language
     objects (names, calls or expressions), or [...]

so it additionally accepts "names" and "calls".

Now, we have

> a <- 2
> foo <- bquote(alpha == .(a))

> foo # Looks OK
alpha == 2
> mode(foo) # But
[1] "call"
> is.expression(foo) # not an expression
[1] FALSE

> is.expression(expression(foo)) ## YES, but
[1] TRUE
> expression(foo) ## not what we want
expression(foo)

> is.expression(as.expression(foo))
[1] TRUE
> as.expression(foo) ## This IS what we want
expression(alpha == 2)

So I submit that lattice is behaving exactly as suggested by its documentation.

Now you would naturally argue that this is hiding behind
technicalities, and if "call" objects work for plot(), it should work
for lattice as well. But watch this:

> plot(1:10, main = foo) # works perfectly

> arglist <- list(1:10, main = foo)
> arglist # Looks like what we want
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

$main
alpha == 2

> do.call(plot, arglist)
Error in as.graphicsAnnot(main) : object 'alpha' not found

...which I would say is "unexpected" behaviour, if not a bug.

The moral of the story is that unevaluated calls are dangerous objects
(try this one out for fun:

foo <- bquote(q(.(x)), list(x = "no"))
do.call(plot, list(1:10, main = foo))

), and carrying them around is not a good idea.

Lattice does use the do.call paradigm quite a bit, and I think it
might be quite difficult to fix it up to handle non-expression
language objects (which will still not fix the type of problem shown
above).

-Deepayan



More information about the R-help mailing list