3

I want to use grid to modify mosaic plots that I create with the vcd package. Specifically, I want to add precisely positioned line segments. Here is a minimal example:

library(vcd)
myDF <- expand.grid(fac1 = c('a', 'b', 'c', 'a'), fac2 = c('y', 'z'))
mosaic(fac2 ~ fac1, data = myDF, pop = FALSE)

The result is this plot:

minimal mosaic plot

I would like to use grid.segments() to draw a horizontal segment under the "fac2" label and as wide as the plotted cells. This would be simple if I could use seekViewport() to navigate to the viewport that holds the "fac2" label. But I can't. Here is the problem:

> getNames()
> [1] "rect:fac1=a,fac2=y" "rect:fac1=a,fac2=z" "rect:fac1=b,fac2=y" "rect:fac1=b,fac2=z" 
  [5] "rect:fac1=c,fac2=y" "rect:fac1=c,fac2=z" "GRID.text.1"        "GRID.text.2"        
  [9] "GRID.text.3"        "GRID.text.4"        "GRID.text.5"        "GRID.text.6"        
 [13] "GRID.text.7" 

When I run seekViewport("cell:GRID.text.2") or anything like it, I get an error message:

Error in grid.Call.graphics(L_downviewport, name$name, strict) : 
  Viewport 'cell:GRID.text.2' was not found

(The "cell:" prefix is part of the vcd viewport-naming scheme. And by contrast, commands like seekViewport("cell:fac1=a,fac2=y") work perfectly.)

Is there a way to navigate to the viewport that holds the "fac2" label? And if not, what is the best way to precisely position a line segment below that label?

user697473
  • 2,165
  • 1
  • 20
  • 47
  • 2
    I think you are looking at the `grob` names rather than the viewports. You can see these by either `grid.ls(viewports=T)` or `current.vpTree(all=T)`, after the plot call. I dont know how to navigate to the viewport with the label, but this seems to get you close to what you want: `vp <- vpPath(current.vpTree()[[2]][[1]][[1]]$name , "base", "margin_top")` ; `grid.segments(y0=0.35,y1=0.35, gp=gpar(col="red", lwd=3), vp=vp)` – user20650 Apr 11 '15 at 00:47

1 Answers1

2

In a comment above, @user20650 provides the necessary information. Among other things, the code in my original post was problematic because getNames() returns grob names, not viewport names.

The simplest way to draw the line segment is to draw the figure as above, and then

nn <- seekViewport("margin_top")  ## Drill down to the viewport[margin_top]
grid.segments(0, .5, 1, .5)
upViewport(nn)                    ## Return to top level viewport, here viewport[ROOT]

The result is this plot:

mosaic plot with line segment between x–axis labels

Community
  • 1
  • 1
user697473
  • 2,165
  • 1
  • 20
  • 47
  • Thanks for coming back to answer this. Nice to see that there's such an elegant solution! Hope you don't mind the couple of edits I just made. – Josh O'Brien Apr 12 '15 at 18:58
  • @JoshO'Brien -- those edits are definitely helpful, especially for people like me who sometimes have trouble navigating viewports. Thank you. – user697473 Apr 12 '15 at 22:31
  • 1
    Cool, thanks. I just edited again, to use `upViewport()` instead of `popViewport()` (which removes the viewport from the tree as it leaves it)! – Josh O'Brien Apr 12 '15 at 22:44