在ggplot中按组堆叠发散条形图

时间:2021-05-20 12:19:20

标签: r ggplot2 charts

我正在尝试制作这样的图表:

enter image description here

我们的想法是绘制 3 个数量,在这个混合堆叠条形图中,我们有一个数据框,其中一行表示负值,两行表示正值,但是我需要将负值与第一个正值条形堆叠在一起,我也需要3种颜色。到目前为止,我的代码如下:(数据框已经具有所需的形状):

df3 <- read.table(
text = 
"region group metric somevalue
blue T1 epsilon 63
blue T2 epsilon -40
red T1 epsilon 100
blue T1 kappa 19
blue T2 kappa -30
red T1 kappa 75
blue T1 zulu  50
blue T2 zulu -18
red T1 zulu 68", header=TRUE)

p2 <- ggplot(df3, aes(x = metric, y = somevalue, fill=region))+
  geom_col(aes(fill = group), width = 0.7) + geom_bar(position = 'dodge', stat='identity')
p2

请帮助我,如果您认为必须修改数据框,请告诉我。谢谢

1 个答案:

答案 0 :(得分:0)

堆叠和躲避总是有点棘手。在您的情况下,这可以像这样实现:

  1. region 转换为 factor。 (这可确保第 3 步有效)
  2. 将您的数据集分为负值和正值两部分。
  3. 使用 tidy::complete 填充数据集,以便每个数据集包含度量、区域和组的“所有”组合。 (这可以确保闪避有效
  4. 使用两个 geom_col 图层使用 position="dodge" 绘制正值和负值。我添加了 na.rm = TRUE 以删除我们通过 complete 添加的缺失值。

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

df3$region <- factor(df3$region)

df3_neg <- filter(df3, somevalue < 0) %>% 
  tidyr::complete(region, group, metric)

df3_pos<- filter(df3, somevalue > 0) %>% 
  tidyr::complete(region, group, metric)

p2 <- ggplot(df3, aes(somevalue, metric)) +
  geom_col(aes(alpha = group, fill=region), data = df3_pos, position = "dodge", na.rm = TRUE) +
  geom_col(aes(alpha = group, fill=region), data = df3_neg, position = "dodge", na.rm = TRUE) +
  scale_fill_identity() +
  scale_alpha_manual(values = c(T2 = .6, T1 = 1)) +
  guides(alpha = FALSE)
p2

EDIT 添加注释可以用同样的方式实现,例如我下面的代码使用两个 geom_text 在我使用 position_dodge2(.9) 的栏旁边添加值,以便标签与栏很好地对齐:


p2 <- ggplot(df3, aes(somevalue, metric)) +
  geom_col(aes(alpha = group, fill=region), data = df3_pos, position = "dodge", na.rm = TRUE) +
  geom_col(aes(alpha = group, fill=region), data = df3_neg, position = "dodge", na.rm = TRUE) +
  geom_text(aes(x = somevalue + 1, label = somevalue), data = df3_pos, position = position_dodge2(width  = .9), hjust = 0, na.rm = TRUE) +
  geom_text(aes(x = somevalue - 1, label = somevalue), data = df3_neg, , position = position_dodge2(width  = .9), hjust = 1, na.rm = TRUE) +
  scale_fill_identity() +
  scale_alpha_manual(values = c(T2 = .6, T1 = 1)) +
  guides(alpha = FALSE)
p2

EDIT2 添加表格确实是另一回事。在这种情况下,我会选择 patchwork,这意味着绘制模拟表格布局的图。为了使躲避工作或确保表格行与您为每个表格列绘制的条形对齐。基本方法可能如下所示:

library(patchwork)

# 1. Make a dataframe with all combinations of region and metric using expand_grid
d_table <- expand_grid(region = unique(df3$region), metric = unique(df3$metric))

# 2. Add columns with the table content
d_table$column1 <- LETTERS[1:6]
d_table$column2 <- letters[1:6]

# 3. Make a plot for each column of the table
p_column1 <- ggplot(d_table, aes(y = metric, x = 1, label = column1)) +
  geom_text(aes(group = region), position = position_dodge2(width = .9), na.rm = TRUE) +
  scale_x_continuous(position = "top", breaks = 1, labels = "column1") +
  labs(y = NULL, x = "") +
  theme(axis.text.y = element_blank(), 
        axis.text.x.bottom = element_blank(),
        axis.ticks = element_blank(), 
        plot.margin = unit(rep(0, 4), "pt"), 
        panel.background = element_rect(fill = NA))
p_column2 <- ggplot(d_table, aes(y = metric, x = 1, label = column2)) +
  geom_text(aes(group = region), position = position_dodge2(width = .9), na.rm = TRUE) +
  scale_x_continuous(position = "top", breaks = 1, labels = "column2") +
  labs(y = NULL, x = "") +
  theme(axis.text.y = element_blank(), 
        axis.text.x.bottom = element_blank(),
        axis.ticks = element_blank(), 
        plot.margin = unit(rep(0, 4), "pt"), 
        panel.background = element_rect(fill = NA))
# 4. Add the table columns via patchwork
p2 + p_column1 + p_column2 + plot_layout(widths = c(1, .1, .1))

enter image description here