y-axis for each subplot using facet_grid

て烟熏妆下的殇ゞ 提交于 2019-12-24 07:58:55

问题


I can't get the answer to this question to work. What both me and that user want is to add axis ticks and labels to all columns when using facet_grid().

Display y-axis for each subplot when faceting

When I run the reproducable example and the solution (after adding abc=as.data.frame(abc) to fix the initial error) I receive an error message

Error in gtable_add_grob(g, grobs = list(segmentsGrob(1, 0, 1, 1), segmentsGrob(1, : Not all inputs have either length 1 or same length same as 'grobs

I made my own reproducible example because the original one is ehhm, a bit odd :-). It results in the same error message

require(ggplot2)
require(reshape)
require(grid)
require(gtable)
data(iris)
iris$category=rep(letters[1:4],length.out=150)
plot1=ggplot(data=iris,aes(x=1,y=Sepal.Width))+geom_boxplot()+facet_grid(Species~category)

The answer should be this:

g <- ggplotGrob(plot1)

require(gtable)
axis <- gtable_filter(g, "axis-l")[["grobs"]][[1]][["children"]][["axis"]][,2]
segment <- segmentsGrob(1,0,1,1)
panels <- subset(g$layout, name == "panel")
g <- gtable_add_grob(g, grobs=list(axis, axis), name="ticks",
                     t = unique(panels$t), l=tail(panels$l, -1)-1)

g <- gtable_add_grob(g, grobs=list(segmentsGrob(1,0,1,1), 
                                   segmentsGrob(1,0,1,1)), 
                     t = unique(panels$t), l=tail(panels$l, -1)-1, 
                     name="segments")

回答1:


The answer you refer to does not apply to your situation.

To get nice placement of the tick marks and tick mark labels, I would add columns to the gtable to take the axis material. The new columns have the same width as the original y axis.

You might want to add more margin space between the panels. Do so with theme(panel.margin.x = unit(1, "lines")).

require(ggplot2)
require(grid)
require(gtable)
data(iris)
iris$category = rep(letters[1:4], length.out = 150)
plot1 = ggplot(data = iris, aes(x = 1, y = Sepal.Width))+
   geom_boxplot()+
   facet_grid(Species~category)

# Get the ggplot grob
g <- ggplotGrob(plot1)

# Get the yaxis
yaxis <- gtable_filter(g, "axis-l")

# Get the width of the y axis
Widths = yaxis$widths

# Add columns to the gtable to the left of the panels, 
# with a width equal to yaxis width
panels <- g$layout[grepl("panel", g$layout$name), ]
pos = rev(unique(panels$l)[-1] - 1)
for(i in pos) g = gtable_add_cols(g, Widths, i)

# Add y axes to the new columns
panels <- g$layout[grepl("panel", g$layout$name), ]
posx = rev(unique(panels$l)[-1] - 1)
posy = unique(panels$t)

g = gtable_add_grob(g, rep(list(yaxis), length(posx)), 
     t = rep(min(posy), length(posx)), b = rep(max(posy), length(posx)), l = posx)

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

Alternatively, place the axis in a viewport of the same width as the original y axis, but with right justification. Then, add the resulting grob to the existing margin columns between the panels, adjusting the width of those columns to suit.

require(ggplot2)
require(grid)
require(gtable)
data(iris)
iris$category = rep(letters[1:4], length.out = 150)
plot1 = ggplot(data = iris, aes(x = 1, y = Sepal.Width))+
   geom_boxplot() + 
   facet_grid(Species ~ category ) 

# Get the ggplot grob
g <- ggplotGrob(plot1)

# Get the yaxis
axis <- gtable_filter(g, "axis-l")

# Get the width of the y axis
Widths = axis$width

# Place the axis into a viewport, 
# of width equal to the original yaxis material,
# and positioned to be right justified
axis$vp = viewport(x = unit(1, "npc"), width = Widths, just = "right")

# Add y axes to the existing margin columns between the panels
panels <- g$layout[grepl("panel", g$layout$name), ] 
posx = unique(panels$l)[-1] - 1
posy = unique(panels$t)

g = gtable_add_grob(g, rep(list(axis), length(posx)), 
     t = rep(min(posy), length(posx)), b = rep(max(posy), length(posx)), l = posx)

# Increase the width of the margin columns
g$widths[posx] <- unit(25, "pt") 
# Or increase width of the panel margins in the original construction of plot1

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



回答2:


This is what I came up (using ggplot2_2.1.0):

g <- ggplotGrob(plot1)
axis <- gtable_filter(g, "axis-l")
newG <- gtable_add_grob(g, list(axis, axis, axis), 
                t = rep(4, 3), b = rep(8, 3), l = c(5, 7, 9))
grid.draw(newG)

..Which looks like this:

This is the process I went through:

  1. g <- ggplotGrob(plot1) Create a gtable.
  2. print(g) Look over the elements of the gtable...I'm looking for the names of the grobs that I want to mess around with. Here, it is the three grobs called "axis-l".
  3. axis <- gtable_filter(g, "axis-l") I select my three grobs from the larger gtable object, g, and save them in a gtable called axis. Note that gtable_filter is actually selecting the grobs, not filtering them from g.
  4. gtable_show_layout(g) Look over the layout of g so I can figure out where I want to put axis in relationship to the overall plot.
  5. gtable_add_grob, etc. Now that I know where I'm going with it, I can append the original plot with axis.

I think that those steps are a pretty common workflow when it comes to gtable. Of course you'll have other stuff that you may what to mess around with. For example, the space that is given for all but the left-most y axis labels is not sufficient in this case. So maybe just:

newG$widths[c(5, 7, 9)] <- grid:::unit.list(axis$widths) # you won't need to wrap this in grid
grid.draw(newG)



来源:https://stackoverflow.com/questions/37619534/y-axis-for-each-subplot-using-facet-grid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!