在ggplot中分割y轴

时间:2018-11-07 23:09:21

标签: r ggplot2

我的数据结构类似于以下结构:

data.frame(x = c("A", "B", "C", "D", "E"), 
           a = abs(rnorm(5)), 
           b = abs(rnorm(5)))

我想以以下方式显示此信息(原谅油漆工作不佳): Example

为此,我编写了以下代码:

set.seed(20)
data.frame(x = c("A", "B", "C", "D", "E"), 
           a = abs(rnorm(5)), 
           b = abs(rnorm(5))) %>%
  mutate(b = -b) %>%
  gather("source", "amount", a, b) %>%
  ggplot(aes(x = x,
             y = amount,
             fill = source)) +
  geom_col() +
  scale_y_continuous(labels = abs)

哪些给了我以下内容:

Result

我将如何沿着y = 0添加间隙并用x轴标签填充?

2 个答案:

答案 0 :(得分:4)

我们可以通过将其移到各个方面来获得大部分方式:

set.seed(20)
data.frame(x = c("A", "B", "C", "D", "E"), 
           a = abs(rnorm(5)), 
           b = abs(rnorm(5))) %>%
  mutate(b = -b) %>%
  gather("source", "amount", a, b) %>%
  ggplot(aes(x = x,
             y = amount,
             fill = source)) +
  geom_col() + 
  scale_y_continuous(labels = abs) +

  # NEW STUFF:
  facet_wrap(~source, ncol=1, scales = "free_y") +
  theme(strip.text = element_blank())

enter image description here

在这里,一种方法是通过制作geom_text层并将其放置在顶面下方的y范围内,从而在中间获得x轴标签。我不知道执行此操作的良好“内置”方法。

data.frame(x = c("A", "B", "C", "D", "E"), 
           a = abs(rnorm(5)), 
           b = abs(rnorm(5))) %>%
  mutate(b = -b) %>%
  gather("source", "amount", a, b) %>%
  ggplot(data = .,
         aes(x = x,
             y = amount,
             fill = source)) +
  geom_col() + 

  # removing minor_breaks avoids grid lines in the middle space
  scale_y_continuous(labels = abs, minor_breaks = NULL) +
  # this creates a single copy of the text, related to one facet
  geom_text(data = . %>% filter(source == "a"), aes(x, y = -.2, label = x)) +
  # this allows for printing outside the plot range
  coord_cartesian(clip = "off") +
  facet_wrap(~source, ncol=1, scales = "free_y", shrink = TRUE ) +
  theme(strip.text = element_blank(),
        axis.text.x = element_blank())

enter image description here

答案 1 :(得分:4)

我可以想到几种解决方法。

您可以尝试使用刻面和自由缩放来棘手,使用我见过的here方法仅标记上轴。

但是,您会看到它在绘图下方留下了一些尴尬的空间,因为它似乎很难删除(但请参见here)。

library(ggplot2)
library(tidyr)
library(dplyr)

set.seed(20)
dat = data.frame(x = c("A", "B", "C", "D", "E"), 
           a = abs(rnorm(5)), 
           b = abs(rnorm(5))) %>%
    mutate(b = -b) %>%
    gather("source", "amount", a, b) %>%
    mutate(x1 = if_else(source == "a",
                          as.character(x), 
                          paste0(as.character(x), 'no_display')))

# function to suppress labels
delete_no_display = function(v) {
    if_else(stringr::str_detect(v, 'no_display'), '', v)
}

ggplot(dat, aes(x = x1,
               y = amount,
               fill = source)) +
    geom_col() +
    facet_wrap(~source, ncol = 1, scales = "free") +
    scale_x_discrete(name = NULL, label = delete_no_display) + 
    scale_y_continuous(name = NULL,
                       labels = abs,
                       breaks = c(-3, -2, -1, 0, 1, 2, 3), 
                       expand = c(0, 0)) +
    theme(strip.background = element_blank(),
        strip.text.x = element_blank(),
        axis.ticks.x = element_blank())

enter image description here

另一个选择是按组分别构建图,然后将它们合并。您可以通过软件包 cowplot 中的函数来执行此操作。如果您决定深入学习,则此软件包有五个helpful vignettes available

此软件包确实对主题有很强的见解,尽管考虑到情节,您尝试制作此主题可能正是您想要的,所以我将其照原样保留。

首先,我绘制了两个图。我在第一个绘图中添加了一个fill图例,但可以根据需要将其删除。

g1 = ggplot(subset(dat, source == "a"), 
            aes(x = x, y = amount, fill = source)) +
    geom_col() +
    scale_x_discrete(name = NULL) + 
    scale_y_continuous(name = NULL, 
                       labels = abs,
                       limits = c(0, 3),
                       expand = expand_scale(mult = c(0, .1) ) ) +
    scale_fill_manual(limits = c("a", "b"), 
                      values = c("#F8766D", "#00BFC4")) +
    theme(plot.margin = margin(0, 0, 0, 0),
          axis.ticks.x = element_blank())

g2 = ggplot(subset(dat, source == "b"), 
            aes(x = x, y = amount, fill = source)) +
    geom_col() +
    scale_x_discrete(name = NULL) + 
    scale_y_continuous(name = NULL, 
                       labels = abs,
                       limits = c(-3, 0),
                       expand = expand_scale(mult = c(.1, 0) ) ) +
    scale_fill_manual(limits = c("a", "b"), 
                      values = c("#F8766D", "#00BFC4"),
                      guide = "none") +
    theme(axis.ticks.x = element_blank(),
          axis.text.x = element_blank(),
          plot.margin = margin(t = 2, unit = "mm"))

然后提取图例并使用plot_grid()组合图(无图例)。

library(cowplot)

legend_a = get_legend(g1)

combined = plot_grid(g1 + theme(legend.position = "none"),
          g2,
          ncol = 1, align = "v")

combined情节如下:

enter image description here

如果需要,您可以重新添加图例(请参见shared legends小插图)和/或放置在整个y轴标签上,如图here所示(尽管图例间距很时髦)。 / p>

plot_grid(combined, legend_a, 
          rel_widths = c(2, .2),
          scale = c(.93, 1)) +
    draw_label("amount", x = 0, y = .5, angle = 90, vjust = 1)

enter image description here

cowplot 方法的不利之处在于,底部的图最终比上方的图稍大。如果我使用align = "hv",我将回到底部有一些多余的空间。最好删除所有轴,然后手动插入标签。我觉得这里有需要收集的信息here,但我没有走那么远。