Adapting to new release

123 views
Skip to first unread message

Dianne Cook

unread,
Sep 7, 2012, 11:08:21 AM9/7/12
to ggplot2
I used these functions to get the text for the tick marks of an axis in the previous version of ggplot2. It now throws an error about gTree. Anybody know what the best way to get the axis tick labels with the new version??

    #pGrob <- ggplotGrob(p)
    #axisBreaks <- as.numeric(getGrob(pGrob, "axis.text.x", grep = TRUE)$label)

cheers,
Di

---------------------------
Di Cook




Brandon Hurr

unread,
Sep 7, 2012, 11:17:57 AM9/7/12
to Dianne Cook, ggplot2
There's a discussion on the development list about how to access elements within the grob table. Apparently 0.92 breaks the ability to call it by name. 

Dennis Murphy is working on a transition guide for the new themeing system in 0.92, but in the meantime some of the devs should be able to help. 

Below is a copy of that email, which might help you with your problem. Sadly, I have no experience with messing with Grobs. 

B

Hi everyone -

A couple questions on the main ggplot2 mailing list have gotten me
thinking about how to access grobs in gtable objects. I'm looking for
some feedback about how to go about doing this.

As you may know, ggplot now generates a gtable object. Here's an
example of how to access and view a gtable:

library(ggplot2)
library(grid)

p <- qplot(1:3, 1:3, colour=c("a", "b", "c"))

# Generate the gtable grob
g <- ggplotGrob(p)

# display it
grid.newpage()
grid.draw(g)

# Print gtable
g
# TableGrob (6 x 6) "layout": 9 grobs
#   (1-6,1-6) background: rect[plot.background.rect.489]
#   (4-4,3-3) spacer: absoluteGrob[GRID.absoluteGrob.462]
#   (3-3,4-4) panel: zeroGrob[NULL]
#   (3-3,3-3) axis-l: gTree[GRID.gTree.450]
#   (4-4,4-4) axis-b: absoluteGrob[GRID.absoluteGrob.456]
#   (5-5,4-4) xlab: text[axis.title.x.text.464]
#   (3-3,2-2) ylab: text[axis.title.y.text.466]
#   (3-3,5-5) guide-box: gtable[guide-box]
#   (2-2,4-4) title: text[plot.title.text.487]

# Layout information is stored in the data frame 'layout'
g$layout
#   t l b r z clip       name
# 9 1 1 6 6 0   on background
# 1 3 3 3 3 3  off     axis-l
# 2 4 3 4 3 1  off     spacer
# 3 3 4 3 4 2   on      panel
# 4 4 4 4 4 4  off     axis-b
# 5 5 4 5 4 5  off       xlab
# 6 3 2 3 2 6  off       ylab
# 7 3 5 3 5 7  off  guide-box
# 8 2 4 2 4 8  off      title

# Access a single grob -- this will get the first one listed in the table
g$grobs[[1]]
# rect[plot.background.rect.489]


As you can see, when you print the gtable object, it displays the name
(taken from the 'layout' column in the data frame) followed by the
type of grob, and finally the grob name (in square brackets). For
example, the first entry in the table is named in the gtable layout
"background", but the name of the grob is "plot.background.rec.489".
I'll call these the layoutName and grobName, respectively. The
layoutName is something used by gtable; the grobName is a property of
the grob itself.

Previously the grobs had grobNames like "background", "axis-l", and so
on. These are now used as the layoutNames, and the grobNames generally
aren't nice and simple like this.

Here are a couple things that seem to be more difficult now:
- I don't think there's a simple way of accessing the grobs by name.
- grid.ls() no longer produces a nice tree of the grob hierarchy.

Any thoughts on how these things could be improved, and what else
could be improved? There may be some other things I'm missing -- feel
free to chime in.

--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: https://github.com/hadley/devtools/wiki/Reproducibility
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

Winston Chang

unread,
Sep 8, 2012, 1:13:48 AM9/8/12
to Dianne Cook, ggplot2
Retrieving it from the ggplot grob is much more complicated now, because of the lack of easy accessor functions in the new gtable structure used by ggplot. It's possible, but ugly. The hard thing about getting the scale breaks is that they're not computed until the ggplot object is rendered, which probably why you had to extract it from the grob in the past.

You can get similar information is to create a scale and train it on your data. For example, this will create a continuous x scale object, train it on the values 1:10, and then retrieve information about the breaks, labels, and range.

sc <- scale_x_continuous()
scale_train_df(sc, data.frame(x = 1:10))
ggplot2:::scale_break_info(sc)

This can be done without even creating a ggplot object. The drawback is that if your plot has stats that modify the data, then the breaks won't match what you get here.



If you must get the labels from the grob, here's some code that does that. Like I said before, it's ugly:
# Create a grob from ggplot
p <- qplot(1:3, 1:3, colour=1:3)
g <- ggplotGrob(p)

# Print the layout.
g$layout
#   t l b r z clip       name
# 9 1 1 6 6 0   on background
# 1 3 3 3 3 3  off     axis-l
# 2 4 3 4 3 1  off     spacer
# 3 3 4 3 4 2   on      panel
# 4 4 4 4 4 4  off     axis-b
# 5 5 4 5 4 5  off       xlab
# 6 3 2 3 2 6  off       ylab
# 7 3 5 3 5 7  off  guide-box
# 8 2 4 2 4 8  off      title

# Here's a simple accessor functions for the grobs:
gt_getgrob <- function(gt, pattern) {
  idx <- grep(pattern, gt$layout$name)
  if (length(idx) > 1)
    stop("More than one match for pattern '", pattern, "'")

  gt$grobs[[idx]]
}


# Get each of the axes
axis_l <- gt_getgrob(g, "axis-l")
axis_b <- gt_getgrob(g, "axis-b")

# Draw them
grid.newpage()
grid.draw(axis_l)
grid.draw(axis_b)


# Extract the labels
axis_l$children[[2]]$grobs[[1]]$label
axis_r$children[[2]]$grobs[[2]]$label


-Winston


Winston Chang

unread,
Sep 10, 2012, 3:22:45 PM9/10/12
to ggplot2
I thought I'd pass this along to the list... In another email, Hadley pointed out a better way to get the break information:

p <- qplot(1:3, 1:3, colour=c("a", "b", "c"))
print(p)$panel$ranges

-Winston
Reply all
Reply to author
Forward
0 new messages