首页 > 解决方案 > 具有三个级别的背靠背条形图:我可以使图居中吗?

问题描述

我希望创建一个背靠背条形图。在我的数据中,我有一些 2017 年和 2018 年的物种观察结果 (n)。有些物种仅在 2017 年出现,有些物种在这两年都出现,有些仅在 2018 年出现。我希望在以物种数量为中心的图表中描述这一点跨多个站点(a,b,c)发生两年。

首先,我创建一个数据集:

n <- sample(1:50, 9)
reg <- c(rep("2017", 3), rep("Both",3), rep("2018", 3))
plot <- c(rep(c("a", "b", "c"), 3))

d4 <- data.frame(n, reg, plot)

我使用 ggplot 尝试绘制图表 - 我尝试了两种方法:

library(ggplot2)
ggplot(d4, aes(plot, n, fill = reg)) +
  geom_col() +
  coord_flip()

ggplot(d4, aes(x = plot, y = n, fill = reg))+
  coord_flip()+
  geom_bar(stat = "identity", width = 0.75)

我得到了一个类似于我想要的情节。但是,希望蓝色的“两者”条位于 2017 年和 2018 年条之间。此外,我的主要问题是,我想将“两者”栏放在情节中间。2017 栏应向左延伸,2018 栏应向右延伸。我的问题有点类似于下面链接中的问题;但是,由于我的图表中只有三个而不是四个级别,我不能使用与下面相同的方法。

使用 ggplot 创建以零为中心的堆积条形图

标签: rggplot2

解决方案


我不确定这是最好的方法,但这是一种方法:

library(dplyr)
d4pos <- d4 %>%
    filter(reg != 2018) %>%
    group_by(reg, plot) %>%
    summarise(total = sum(n)) %>% 
    ungroup() %>%
    mutate(total = total * ifelse(reg == "Both", .5, 1))
d4neg <- d4 %>%
    filter(reg != 2017) %>%
    group_by(reg, plot) %>%
    summarise(total = - sum(n)) %>% 
    ungroup() %>%
    mutate(total = total * ifelse(reg == "Both", .5, 1))

ggplot(data = d4pos, aes(x = plot, y = total, fill = reg)) + 
    geom_bar(stat = "identity") + 
    geom_bar(data = d4neg, stat = "identity", aes(x = plot, y = total, fill = reg)) + 
    coord_flip()

我为每组的总数生成两个数据框。一个包含 2017 年和(一半)​​两者,另一个包含其余部分。2018 年数据框的值被翻转以绘制在负侧。

输出如下所示:

在此处输入图像描述

编辑 如果你想在水平轴的两个方向上都有正值,你可以这样做:

ggplot(data = d4pos, aes(x = plot, y = total, fill = reg)) + 
    geom_bar(stat = "identity") + 
    geom_bar(data = d4neg, stat = "identity", aes(x = plot, y = total, fill = reg)) + 
    scale_y_continuous(breaks = seq(-50, 50, by = 25), 
                       labels = abs(seq(-50, 50, by = 25))) +
    coord_flip() 

推荐阅读