Skip to content

lattice: how to "center" a subtitle?

15 messages · Marius Hofert, Peter Ehlers, Henrique Dallazuanna +3 more

#
Dear expeRts,

I recently asked for a real "centered" title (see, e.g., http://tolstoy.newcastle.edu.au/R/e13/help/11/01/0135.html). 
A nice solution (from Deepayan Sarkar) is to use "xlab.top" instead of "main":

library(lattice)
trellis.device("pdf") 
print(xyplot(0 ~ 0, xlab.top = "This title is now 'centered' for the human's eye", sub = "but subtitles are not centered", scales = list(alternating = c(1,1), tck = c(1,0)))) 
dev.off()

My question is whether there is something similar for *sub*titles [so something like "xlab.bottom"]? As you can see from the plot, the subtitle does not seem to be "centered" for the human's eye. I would like to center it according to the x-axis label. 

Cheers,

Marius
#
On Apr 4, 2011, at 7:39 AM, Marius Hofert wrote:

            
library(lattice)
trellis.device("pdf")
print(xyplot(0 ~ 0, xlab.top = "This title is now 'centered' for the  
human's eye", xlab = "but subtitles are _now_ centered", scales =  
list(alternating = c(1,1), tck = c(1,0))))
dev.off()


(I realize that those are not really subtitles by a 'lab', but that  
appears acceptable in your current test case.)
David Winsemius, MD
West Hartford, CT
#
Dear David,

I intended to use another x-label. But your suggestion brings me to the idea of just using a two-line xlab, so s.th. like
print(xyplot(0 ~ 0, xlab.top = "This title is now 'centered' for the human's eye", xlab = "but subtitles are _now_ centered\nbla", scales = list(alternating = c(1,1), tck = c(1,0))))

Thanks!

Cheers,

Marius
On 2011-04-04, at 16:47 , David Winsemius wrote:

            
#
On Apr 4, 2011, at 12:45 PM, Marius Hofert wrote:

            
And if you wanted different fontface (underline, italic or bold) then  
you could use plotmath expressions:

xyplot(0 ~ 0, xlab.top = "This title is now 'centered' for the human's  
eye", xlab =  
expression( atop(but~subtitles2~are~underline(now)~centered,  
bold(bla) )), scales = list(alternating = c(1,1), tck = c(1,0)))
#
Dear David,

do you know how to get plotmath-like symbols in both rows?
I tried s.th. like:

lab <- expression(paste(alpha==1, ", ", beta==2, sep=""))
xlab <- substitute(expression( atop(lab==lab., bold(foo)) ), list(lab.=lab))
xyplot(0 ~ 0, xlab = xlab)

Cheers,

Marius
On 2011-04-04, at 18:59 , David Winsemius wrote:

            
#
On Apr 4, 2011, at 1:27 PM, Marius Hofert wrote:

            
I _did_ have plotmath functions in both rows: But here is your solution:

xyplot(0 ~ 0,  xlab =
     expression( atop(paste(alpha==1, "   ", beta==2), bold(bla) )) )
       )

Note that `paste` in plotmath is different than `paste` in regular R.  
It has no `sep` argument. I did try both substitute and bquote on you  
externally expression,  but lattice seems to be doing some non- 
standard evaluation and I never got it to "work". Using what I thought  
_should_ work, does work with `plot`:

 > x=1;y=2
 > plot(0 ~ 0, xlab = bquote( atop(alpha==.(x)*","~beta==.(y),  
bold(foo) ) )
+ )

But the same expression throws an error with xyplot:
 > x=1;y=2
 > xyplot(0 ~ 0, xlab = bquote( atop(alpha==.(x)*","~beta==.(y),  
bold(foo) ) )
+ )
Error in trellis.skeleton(formula = 0 ~ 0, cond = list(1L), aspect =  
"fill",  :
   could not find function "atop"
#
On 2011-04-04 10:27, Marius Hofert wrote:
Marius,

I always find paste a bit tricky with plotmath.
Maybe this will do what you want:

  mylab <- expression( atop(lab==list(alpha==1, beta==2), bold(foo)) )
  xyplot(0 ~ 0, xlab = mylab)

Peter Ehlers
#
Maybe:

xyplot(0 ~ 0, xlab =
bquote(expression(atop(alpha==.(x)*","~beta==.(y), bold(foo) )) ))
On Mon, Apr 4, 2011 at 2:58 PM, David Winsemius <dwinsemius at comcast.net> wrote:

  
    
#
Dear all,

many thanks, that helped a lot!

Cheers,

Marius
On 2011-04-04, at 19:58 , David Winsemius wrote:

            
#
On 05/04/11 05:58, David Winsemius 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 .....

David Scott
#
On Apr 4, 2011, at 8:42 PM, David Scott wrote:

            
I did. Your theory seems supported by the experimental evidence:

lab <- bquote(paste(alpha==1, ", ", beta==2))
xyplot(0 ~ 0, xlab = as.expression(bquote(atop(.(lab), bold(foo) ) )))

# Works!
Right. It does seem as though we should need to be deducing the inner  
workings of the subatomic particles by throwing text at the  
interpreter though.
#
On Apr 4, 2011, at 9:03 PM, David Winsemius wrote:

            
Perhaps here:
http://finzi.psych.upenn.edu/Rhelp10/2010-August/250832.html

Or here:
http://finzi.psych.upenn.edu/Rhelp10/2009-July/203714.html

Although I disagree with Heimstra that reading the help(bquote)  
provides "more details" that might shed light on why this is so.
#
On 05/04/11 13:14, David Winsemius wrote:
I am pretty sure that was where I saw it. I knew it was out there somewhere.
David Scott
#
On Tue, Apr 5, 2011 at 6:12 AM, David Scott <d.scott at auckland.ac.nz> wrote:
[...]
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
alpha == 2
[1] "call"
[1] FALSE
[1] TRUE
expression(foo)
[1] TRUE
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:
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

$main
alpha == 2
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
#
On 6/04/2011 12:47 a.m., Deepayan Sarkar wrote:
Thanks very much for this explanation Deepayan. Part of my intention in 
contributing to this thread was to have something explicit in the 
archives for future reference, and your reply is excellent in that regard.

And many thanks for your work on lattice.

David Scott