首页 > 解决方案 > 使用 strip.y 作为 strip.x 而不翻转 facet_grid 轴

问题描述

用代码

library(ggplot2)
library(dplyr)

mydata = tribble(
  ~x, ~y, ~data, ~more,
  0, 50, 'iris', 'this', 
  10, 100, 'iris', 'this',
  0, 50, 'iris', 'that', 
  10, 100, 'iris', 'that',
  0, 0, 'wine', 'this', 
  10, 10, 'wine', 'this',
  0, 0, 'wine', 'that', 
  10, 10, 'wine', 'that',
)

ggplot(mydata, aes(x,y)) + facet_grid(data~more, scale='free') + theme_gray() + geom_point()

ggplot(mydata, aes(x,y)) + facet_grid(more~data, scale='free') + theme_gray() + geom_point()

我正在获取图形:

在此处输入图像描述

在此处输入图像描述

请注意,第一张图表填充面板中的空间要好得多。因为我的真实情节用颜色编码,我不需要显示“这个”和“那个”,所以我想在第一个情节中去掉它。但是随后数据标签在侧面很奇怪。如果他们是这样的,我会更喜欢:

在此处输入图像描述

这类似于ggplot2: Using gtable to move strip labels to panel top for facet_grid,但其他链接对我不起作用,我认为情况有点不同。

我怎样才能做到这一点?

标签: rggplot2

解决方案


要使条带跨越列,您可能需要使用gtable函数(和几个grid函数)。

在解决方案中,将行添加到图表的 gtable 中,然后将条添加到新行中。条带可以从头开始构建,但绘制第二张条带水平方向的图表可能更容易,然后提取条带。

(注意:这很容易与下一个 ggplot 版本中断。)

library(ggplot2)
library(dplyr)


mydata = tribble(
  ~x, ~y, ~data, ~more,
  0, 50, 'iris', 'this', 
  10, 100, 'iris', 'this',
  0, 50, 'iris', 'that', 
  10, 100, 'iris', 'that',
  0, 0, 'wine', 'this', 
  10, 10, 'wine', 'this',
  0, 0, 'wine', 'that', 
  10, 10, 'wine', 'that',
)

### Construct two charts:
# 1. ToKeep - the data~more chart, but without the strip labels. 
# The strips across the tops of the two rows of panels will be added later.

(ToKeep <- ggplot(mydata, aes(x,y)) + 
           facet_grid(data ~ more, scale ='free') + 
           geom_point() +
           theme(strip.text.y = element_blank(),
                 strip.text.x= element_blank()) )

# 2. ToGetStrip - Get the strips from the more~data chart
ToGetStrip <- ggplot(mydata, aes(x,y)) + 
              facet_grid(more ~ data, scale = 'free') +
              geom_point()

# Get the ggplot grob
gt = ggplotGrob(ToGetStrip)

# Get the strips
library(gtable)
library(grid)
strip = gtable_filter(grid.force(gt), "strip-t")


# Make sure
grid.newpage()
grid.draw(strip$grobs[[1]])

grid.newpage()
grid.draw(strip$grobs[[2]])


## Add the strips to the ToKeep chart.

# Get ggplot grob
gt = ggplotGrob(ToKeep)

# Check heights and widths
gt$heights
gt$widths

# The 1null heights and widths are the panels' heights and widths.
# Add rows to the gtable immediately above the panel rows (that is, after row 9 then row 7).
# The height of the new rows is the height of the strip grobs.

gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = 9)
gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = 7)

# Add the strips to the new rows (  t = c(8, 11)  )
# and make sure they span the two columns of panels (  l = 5, r = 7   ) 
gt <- gtable_add_grob(gt, list(strip$grobs[[1]], strip$grobs[[2]]), t = c(8, 11), l = 5, r = 7)

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

在此处输入图像描述

以下是根据面板位置选择行和列的尝试。但是,它尚未在您的 2 X 2 图表之外进行测试。(这可能对 ggplot 的更改更具弹性。)

# Construct the two charts
ToKeep <- ggplot(mydata, aes(x,y)) + 
           facet_grid(data ~ more, scale ='free') + 
           geom_point() +
           theme(strip.text.y = element_blank(),
                 strip.text.x= element_blank())


ToGetStrip <- ggplot(mydata, aes(x,y)) + 
              facet_grid(more ~ data, scale = 'free') +
              geom_point()

# Get the strips from the second chart
gt = ggplotGrob(ToGetStrip)

library(grid)
library(gtable)
strip = gtable_filter(grid.force(gt), "strip-t")


# Add rows to the ToKeep chart, and add the strips to the new rows
gt = ggplotGrob(ToKeep)
PanelPos = subset(gt$layout, grepl("panel", gt$layout$name), select = t:r)

PanelRows = rev(unique(PanelPos$t))
for(i in seq_along(PanelRows)) {
gt <- gtable_add_rows(gt, height = strip$grobs[[1]]$height, pos = PanelRows[i]-1)
}

PanelRows = unique(subset(gt$layout, grepl("panel", gt$layout$name), select = t, drop = TRUE))
gt <- gtable_add_grob(gt, strip$grobs, t = PanelRows - 1, l = min(PanelPos$l), r = max(PanelPos$r))

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

推荐阅读