使用facet_wrap和geom_segment删除不必要的y轴点

时间:2017-08-20 03:00:21

标签: r ggplot2

我使用geom_segment()将y轴点映射到x轴,然后使用facet_wrap将数据分成两个图;但是,y轴点在两个图上都显示出来。

如何只有每个facet_wrap所需的y轴点?

示例代码

dat <- structure(list(temp = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 
4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5), rev = c(-5, 
-11, -20, -29, -40, -9, -20, -32, -45, -57, -12, -24, -37, -50, 
-62, -7, -20, -36, -52, -67, -5, -13, -23, -35, -47, -12, -24, 
-36, -48, -58), type = c("Type 1", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 1", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 2", "Type 2"), model = c("A", 
"A", "A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "C", 
"C", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "C", "C", 
"C", "C", "C")), .Names = c("temp", "rev", "type", "model"), row.names = c(NA, 
-30L), class = "data.frame")

p1 <- ggplot(dat, aes(temp, rev, color = model)) + 
  geom_line() + geom_point() + geom_segment(aes(x = 0, xend = temp, yend = rev), linetype = "dashed", color = "grey") + 
  facet_wrap(~type, scales = "free") + scale_y_continuous(breaks = dat$rev)
p1

剧情

enter image description here

2 个答案:

答案 0 :(得分:4)

我制作了虚拟数据,因为出于某种原因将dput粘贴到我的控制台中使它变得不快乐。

library(dplyr)

df <- expand.grid(temp = 1:5, model = LETTERS[1:3], type = 1:2) %>% 
  group_by(model, type) %>% 
  mutate(rev = -sort(sample.int(20, length(temp)))) 

# this is equivalent to your data as-is, structurewise
df.labeled <- df %>% 
  ungroup() %>% group_by(type, rev) %>% 
  mutate(label = c(rev[1], rep(NA, length(rev) - 1)))

在这里,我为每个组值面板中显示的每个y值创建了一个组。然后我创建一个label列,其中包含1个y值的观察值,用NA s填充。因此,如果某个小组有两个模型,每个模型都有rev -5,那么现在它将是-5, NA而不是-5, -5。为什么我这样做会在下面变得更清楚。

ggplot(df.labeled, aes(temp, rev, color = model)) + 
  geom_segment(aes(xend = 0, yend = rev), linetype = "dashed", color = "grey") +
  geom_text(aes(label = label, x = -0.1), colour = "black", hjust = 1) +
  geom_vline(xintercept = 0) +
  geom_point() + geom_line() + facet_grid(~type) + 
  scale_y_continuous(breaks = NULL) + 
  scale_x_continuous(limits = c(-0.5, NA)) +
  theme_bw() + theme(panel.grid = element_blank())

enter image description here

如果我留下了重复项(这里将是-7,类型1为-15,类型2为-11),geom_text将是一个混乱的粗体模糊。重复的文字标签在ggplot2中无法很好地呈现。因为它不可能按照你想要的方式去做,所以我们只是为每个面板制作一个假比例。如果你不喜欢在数字左边的y轴上有一条额外的线的事实,那就可以摆脱:

  ... + 
  theme(panel.grid = element_blank(),
        panel.border = element_blank(),
        axis.line.x = element_line())

enter image description here

答案 1 :(得分:2)

我们可以按type拆分数据框,创建单独的图,然后使用grid.arrange包中的gridExtra来合并两个图。

library(ggplot2)
library(gridExtra)

# Split the data
dat_list <- split(dat, dat$type)

# Use lapply to create plot for both subset
p_list <- lapply(dat_list, function(x){

  p1 <- ggplot(x, aes(temp, rev, color = model)) + 
    geom_line() + 
    geom_point() + 
    geom_segment(aes(x = 0, xend = temp, yend = rev), linetype = "dashed", color = "grey") + 
    scale_y_continuous(breaks = x$rev) +
    facet_wrap(~type, scales = "free")
  return(p1)
})

# Plot the data
grid.arrange(grobs = p_list, nrow = 1)

更新

另一种选择是使用cowplot包。这似乎是一种创造共同传奇的方式。

library(cowplot)

# Get the common legend, p_list is from the previous example
legend_both <- get_legend(p_list[[1]])

# Plot the plots and the common legend together
# Use rel_widths to set the column width
plot_grid(p_list[[1]] + theme(legend.position = "none"),
          p_list[[2]] + theme(legend.position = "none"),
          legend_both, 
          nrow = 1,
          rel_widths = c(2, 2, 1))