You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot堆叠条形图中添加符号作为第三变量

问题描述

现有一个基于两个变量的ggplot堆叠条形图,希望将第三个变量circumstances_bite_avoidability以符号/图形元素的形式添加到图中(效果为在每个物种条形的右侧添加代表「可避免/不可避免」的区分符号)。

当前使用的代码:

sur %>% 
  filter(!(species_broad %in% c("Monkey", "Cattle"))) %>%
  drop_na(circumstances_bite_broad_intended) %>%
  add_count(species_broad) %>%
  mutate(y_species_broad = 
           reorder(
             factor(paste0(species_broad, "\n", "(n = ", n, ")")),
             as.numeric(species_broad)
           )) %>% 
  ggplot(mapping=aes(y= y_species_broad, fill=circumstances_bite_broad_intended)) + 
  geom_bar(colour="black" , position = "fill")+ 
  scale_x_continuous (labels=c("0","25%","50%","75%","100%"))  +
  labs (x="Proportion of responses",y="Animal species" , fill="Circumstances")+  # "fill" to change the legend title 
  ggtitle ("Circumstances of bite in different animal species")+ 
  scale_fill_manual( values =c ("Threatening Engagement" = "darkred" ,
                                "Friendly Engagement" = "red" , 
                                "Practical Engagement" = "#EC7979" ,
                                "Unintentional Human Engagement" = "lightblue" ,
                                "Apparently unprovoked" = "darkblue"))

使用的数据集:

structure(list(species = structure(c(1L, 1L, 3L, 5L, 1L, 2L, 
7L, 2L, 2L, 1L, 3L, 1L, 2L, 3L, 1L, 2L, 1L, 4L, 4L, 7L, 2L, 1L, 
2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 2L, 3L, 2L, 1L, 1L, 1L, 6L, 7L, 9L), levels = c("Pet dog", 
"Unowned dog", "Dog (unknown status)", "Pet cat", "Unowned cat", 
"Cat (unknown status)", "Rat/rodent", "Monkey", "Cattle"), class = "factor"), 
    circumstances_bite_avoidability = structure(c(1L, 2L, 1L, 
    1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 
    1L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 
    1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
    2L, NA), levels = c("Avoidable", "Unavoidable"), class = "factor"), 
    circumstances_bite_broad_intended = structure(c(2L, 4L, 1L, 
    3L, 4L, 4L, 4L, 5L, 5L, 3L, 5L, 1L, 4L, 5L, 5L, 1L, 5L, 5L, 
    2L, 5L, 4L, 3L, 5L, 2L, 2L, 5L, 4L, 3L, 3L, 5L, 1L, 5L, 1L, 
    1L, 5L, 5L, 4L, 4L, 5L, 1L, 5L, 5L, 1L, 1L, 5L, 5L, 2L, 3L, 
    5L, NA), levels = c("Threatening Engagement", "Friendly Engagement", 
    "Practical Engagement", "Unintentional Human Engagement", 
    "Apparently unprovoked"), class = "factor")), row.names = c(NA, 
50L), class = "data.frame")
解决方案

要实现需求,需要先对第三个变量做汇总统计,再将符号添加到堆叠条形的右侧,具体步骤如下:

1. 数据预处理

先补全原代码中缺失的species_broad变量逻辑,同时统计每个物种的「可避免/不可避免」相关数据:

library(tidyverse)

sur_processed <- sur %>%
  # 生成species_broad分组(对齐原代码逻辑)
  mutate(species_broad = case_when(
    str_detect(species, "dog|Dog") ~ "Dog",
    str_detect(species, "cat|Cat") ~ "Cat",
    species == "Rat/rodent" ~ "Rat/rodent",
    TRUE ~ as.character(species)
  )) %>%
  filter(!(species_broad %in% c("Monkey", "Cattle"))) %>%
  drop_na(circumstances_bite_broad_intended, circumstances_bite_avoidability) %>%
  # 统计每个物种总样本数
  add_count(species_broad, name = "total_n") %>%
  # 统计每个物种下可避免/不可避免的数量
  group_by(species_broad, circumstances_bite_avoidability) %>%
  mutate(avoid_count = n()) %>%
  ungroup() %>%
  # 生成y轴标签(和原代码一致)
  mutate(y_species_broad = reorder(
    factor(paste0(species_broad, "\n", "(n = ", total_n, ")")),
    as.numeric(species_broad)
  )) %>%
  # 去重,保留每个物种+避免性的唯一行用于添加符号
  distinct(species_broad, y_species_broad, circumstances_bite_avoidability, avoid_count, total_n)

2. 绘制带符号的堆叠条形图

在原有绘图逻辑基础上,添加geom_text放置区分符号,同时扩展x轴范围容纳符号:

ggplot(sur_processed, aes(y = y_species_broad)) +
  # 绘制原堆叠条形图(还原原始行数保证比例正确)
  geom_bar(data = sur_processed %>% 
             select(-circumstances_bite_avoidability, -avoid_count) %>%
             uncount(total_n),
           aes(fill = circumstances_bite_broad_intended),
           colour = "black", position = "fill") +
  # 添加符号:对勾代表可避免,叉号代表不可避免
  geom_text(aes(x = 1.05, 
                label = ifelse(circumstances_bite_avoidability == "Avoidable", "✔", "✖"),
                color = circumstances_bite_avoidability),
            size = 5, position = position_dodge(0.8)) +
  # 坐标轴设置:扩展x轴范围
  scale_x_continuous(labels = c("0","25%","50%","75%","100%"),
                     limits = c(0, 1.2)) +
  # 颜色映射(保留原配色)
  scale_fill_manual(values = c(
    "Threatening Engagement" = "darkred",
    "Friendly Engagement" = "red",
    "Practical Engagement" = "#EC7979",
    "Unintentional Human Engagement" = "lightblue",
    "Apparently unprovoked" = "darkblue"
  )) +
  scale_color_manual(values = c("Avoidable" = "green", "Unavoidable" = "darkred")) +
  # 标签设置
  labs(x = "Proportion of responses",
       y = "Animal species",
       fill = "Circumstances",
       color = "Avoidability",
       title = "Circumstances of bite in different animal species") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

补充说明

  • 如果不想用文本符号,可替换为geom_point,通过shape参数设置不同图形(比如shape=16代表实心圆,shape=1代表空心圆)区分类别。
  • 扩展x轴范围limits = c(0, 1.2)是为了防止符号超出绘图区域。
  • 若需要展示「可避免/不可避免」的比例,可将符号位置或大小绑定到avoid_count/total_n变量。

内容的提问来源于stack exchange,提问作者Rakesh Chand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:44:52