【问题标题】:Force x-axis labels on facet_grid ggplot: x-axis labels differ per row在 facet_grid ggplot 上强制 x 轴标签:x 轴标签每行不同
【发布时间】:2014-11-17 02:19:20
【问题描述】:

我很高兴在帖子 "Force X axis text on for all facets of a facet_grid plot" 中找到了我问题的大部分解决方案。

我想创建一个看起来有点像 OP Drew Steen 的图表,除了我有超过两行的刻面,我想让每行的 x 轴标签不同。

我根据@baptiste 的精彩回答做了一个超级hacky 的解决方案(主要是因为我不熟悉 gtable 包),我想知道:

  1. 如果有比我在下面写的烂摊子更优雅的解决方案
  2. 如何为“Premium”(中间)行插入标签。

这是我改编自@Drew Steen 和@baptiste 的代码,

library(ggplot2)

diamondSub <-subset(diamonds, (cut=="Ideal" | cut=="Premium" | cut == "Very Good") & (color=="E" | color=="I"))

p<- ggplot(diamondSub, aes(x=carat, y=price)) + 
  geom_blank()+ 
  geom_point() +
  scale_x_discrete(breaks=c(1, 2, 3, 4), labels=c("a", "b", "c", "d")) +
  facet_grid(cut~color, scales="free_x")
p

p2<- ggplot(diamondSub, aes(x=carat, y=price)) + 
  geom_blank()+ 
  geom_point() +
  scale_x_discrete(breaks=c(1, 2, 3, 4), labels=c("f", "g", "h", "i")) +
  facet_grid(cut~color, scales="free_x")
p2

library(gtable)

g <- ggplotGrob(p)
g2 <- ggplotGrob(p2)

# locate the panels
panels <- grep("panel", g$layout$name)
panels2 <- grep("panel", g2$layout$name)

top <- unique(g$layout$t[panels])
top2 <- unique(g2$layout$t[panels2])
# intersperse a copy of the bottom axes
all <- gtable:::rbind_gtable(gtable:::rbind_gtable(g[seq.int(min(top)), ], 
                                                   g[max(top)+1,], "first"), 
                             g2[seq(min(top2)+1, nrow(g2)),], "first")
grid.newpage()
grid.draw(all)

【问题讨论】:

    标签: r plot ggplot2 facet gtable


    【解决方案1】:

    替代版本(2015 年 4 月 24 日添加)显示元素的手动构造并包含更多评论。

    ## Alternative version
    library(gtable)
    library(grid)
    
    # Get the ggplot grobs
    g <- ggplotGrob(p)
    g2 <- ggplotGrob(p2)
    
    # Show the layout.
    # Note the rows and columns
    # In this case, the g2 layout is the same as the g layout
    gtable_show_layout(g)
    
    # The large panels are the plot panels.
    # We will need rows 4, 6 and 8.
    
    # For the top "Very Good" row, we will also need rows 1, 2, and 3.
    
    # The axis is located in row 9
    
    # Therefore rbind the grob in rows 1, 2, 3, and 4, with the grob in row 9.
    top.row <- rbind(g[1:4, ], g[9, ], size = "first")
    
    # The second "Premium" row
    # We need the panels in row 6 plus the small gap row above,
    # and rbind that to the axis
    middle.row = rbind(g2[5:6, ], g2[9,], size = "first")
    
    # The bottom "Ideal" row
    # We need the panel in row 8 plus the small gap in the row above
    # plus the axis in the row below
    # plus rows below that (axis label and margin)
    bottom.row = g2[7:11, ]
    
    
    # rbind the three rows 
    all <- rbind(rbind(top.row, middle.row, size = "first"), bottom.row, size = "first")
    
    # Draw it
    grid.newpage()
    grid.draw(all)
    
    # Maybe add a little more space between the rows
    gtable_show_layout(all)
    all$heights[c(6,9)] = unit(1, "lines")
    
    # Draw it
    grid.newpage()
    grid.draw(all)
    

    但是您甚至不需要将面板绑定到轴;只需从布局中选择适当的行:

    top.row <- g[c(1:4, 9), ]
    middle.row = g2[c(5:6, 9), ]
    bottom.row = g2[7:11, ]
    

    然后绑定这三个新行。

    原版

    您只在绑定行时犯了错误。您已将轴绑定到顶部的“非常好”行。底部的“理想”行已经有一个轴,因此不需要绑定。修复:中间的“Premium”行需要一个轴。

    我分别构建了每一行,将轴绑定到顶部和中间行,然后绑定三行。

    我添加了另一个步骤,以便在行之间添加更多空间。

    g <- ggplotGrob(p)
    g2 <- ggplotGrob(p2)
    
    # locate the panels
    panels <- grep("panel", g$layout$name)
    panels2 <- grep("panel", g2$layout$name)
    
    top <- unique(g$layout$t[panels])
    top2 <- unique(g2$layout$t[panels2])
    
    # Construct each row separately
    top.row <- gtable:::rbind_gtable(g[seq.int(min(top)), ], g[max(top)+1,], "first")
    middle.row <- gtable:::rbind_gtable(g2[c(top[2]-1,top[2]), ], g2[max(top)+1,], "first")
    bottom.row <- g2[(max(top2)-1):nrow(g2), ]
    
    all <- gtable:::rbind_gtable(gtable:::rbind_gtable(top.row, middle.row, "first"), bottom.row, "first")
    
    # Draw it
    grid.newpage()
    grid.draw(all)
    
    # Maybe add a little more space between the rows
    all$heights[c(6,9)] = unit(1, "lines")
    
    grid.newpage()
    grid.draw(all)
    

    【讨论】:

    • 这让我的脸上露出了笑容——我仍然真的需要弄清楚这一点;我希望使用这个相当多!它对我来说效果很好。谢谢你。您是否考虑对代码进行更多注释以帮助 gtable 初学者了解每个阶段发生的情况?例如,当我们创建“面板”时,我知道我们正在定位 TableGrob 中存储面板信息的行,然后找到这些面板的顶部____,但之后我迷失了构造的语法每一行。如果我修改它,那将非常有帮助。再次感谢!
    • @Nova,我添加了一个替代版本,它可以手动构建组件,并带有额外的注释。
    猜你喜欢
    • 2018-11-03
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2021-08-12
    相关资源
    最近更新 更多