使用R的ggplot绘制按微生物与抗生素分组的循环堆叠条形图
用ggplot绘制按微生物和抗生素分组的堆叠条形图
问题背景
我正在尝试用R的ggplot绘制堆叠条形图,现有如下数据框:
| 样本(Sample) | 日期(Date) | 微生物(Organism) | 抗生素(Antibiotic) | 耐药性(Resistance) |
|---|---|---|---|---|
| 1 | 01/01/2020 | E Coli | Amoxicillin | S |
| 1 | 01/01/2020 | E Coli | Gentamicin | S |
| 1 | 01/01/2020 | E Coli | Cefalexin | R |
| 2 | 01/01/2020 | S aureus | Amoxicillin | S |
| 2 | 01/01/2020 | S aureus | Gentamicin | S |
| 2 | 01/01/2020 | S aureus | Cefalexin | R |
| 3 | 01/01/2020 | E Coli | Amoxicillin | S |
| 3 | 01/01/2020 | E Coli | Gentamicin | S |
| 3 | 01/01/2020 | E Coli | Cefalexin | S |
| 4 | 02/01/2020 | S aureus | Amoxicillin | S |
| 4 | 02/01/2020 | S aureus | Gentamicin | S |
| 4 | 02/01/2020 | S aureus | Cefalexin | R |
| 5 | 02/01/2020 | E coli | Amoxicillin | R |
| 5 | 02/01/2020 | E coli | Gentamicin | S |
| 5 | 02/01/2020 | E coli | Cefalexin | R |
| 6 | 03/01/2020 | E coli | Amoxicillin | R |
| 6 | 03/01/2020 | E coli | Gentamicin | R |
| 6 | 03/01/2020 | E coli | Cefalexin | S |
| 7 | 04/01/2020 | E coli | Amoxicillin | S |
| 7 | 04/01/2020 | E coli | Gentamicin | S |
| 7 | 04/01/2020 | E coli | Cefalexin | S |
| 8 | 04/01/2020 | S aureus | Amoxicillin | S |
| 8 | 04/01/2020 | S aureus | Gentamicin | S |
| 8 | 04/01/2020 | S aureus | Cefalexin | S |
| 9 | 05/01/2020 | Kleb pneumo | Amoxicillin | S |
| 9 | 05/01/2020 | Kleb pneumo | Gentamicin | S |
| 9 | 05/01/2020 | Kleb pneumo | Cefalexin | S |
| 10 | 05/01/2020 | Kleb pneumo | Amoxicillin | R |
| 10 | 05/01/2020 | Kleb pneumo | Gentamicin | R |
| 10 | 05/01/2020 | Kleb pneumo | Cefalexin | R |
| 11 | 05/01/2020 | E coli | Amoxicillin | S |
| 11 | 05/01/2020 | E coli | Gentamicin | S |
| 11 | 05/01/2020 | E coli | Cefalexin | S |
| 12 | 06/01/2020 | S aureus | Amoxicillin | S |
| 12 | 06/01/2020 | S aureus | Gentamicin | S |
| 12 | 06/01/2020 | S aureus | Cefalexin | S |
| 13 | 06/01/2020 | Kleb pneumo | Amoxicillin | S |
| 13 | 06/01/2020 | Kleb pneumo | Gentamicin | S |
| 13 | 06/01/2020 | Kleb pneumo | Cefalexin | S |
| 14 | 06/01/2020 | Kleb pneumo | Amoxicillin | R |
| 14 | 06/01/2020 | Kleb pneumo | Gentamicin | R |
| 14 | 06/01/2020 | Kleb pneumo | Cefalexin | R |
需求说明
需要绘制以Date为x轴,按每种Organism和Antibiotic分组的堆叠条形图,包含两种类型:
- 每日样本计数
- 每日样本占比
日期已通过as.Date()转换为日期格式,当前代码只能生成按Resistance分组的百分比堆叠图,无法实现按Organism和Antibiotic分组,现有代码如下:
ggplot(sens_df, aes(fill=Resistance, , x=Date)) + geom_bar(position="fill", stat="count") + scale_fill_brewer(palette = "Set3")
解决方案
步骤1:预处理数据(统一微生物名称)
数据中存在E Coli和E coli这类同物异名,先统一格式:
library(dplyr) library(ggplot2) sens_df <- sens_df %>% mutate(Organism = toupper(Organism)) %>% mutate(Organism = gsub("E COLI", "E. COLI", Organism)) %>% mutate(Organism = gsub("S AUREUS", "S. AUREUS", Organism)) %>% mutate(Organism = gsub("KLEB PNEUMO", "KLEBSIELLA PNEUMONIAE", Organism))
步骤2:绘制每日样本计数堆叠图
合并微生物+抗生素+耐药性为单一分组
ggplot(sens_df, aes(x = Date, fill = interaction(Organism, Antibiotic, Resistance))) + geom_bar(stat = "count") + labs(title = "每日样本耐药性计数(按微生物+抗生素分组)", x = "日期", y = "样本计数", fill = "分组(微生物+抗生素+耐药性)") + scale_fill_brewer(palette = "Set3") + theme(axis.text.x = element_text(angle = 45, hjust = 1))
按微生物分面,展示抗生素+耐药性堆叠
如果希望更清晰区分不同微生物,可使用分面:
ggplot(sens_df, aes(x = Date, fill = interaction(Antibiotic, Resistance))) + geom_bar(stat = "count") + facet_wrap(~Organism) + labs(title = "每日样本耐药性计数(按微生物分面)", x = "日期", y = "样本计数", fill = "抗生素+耐药性") + scale_fill_brewer(palette = "Set3") + theme(axis.text.x = element_text(angle = 45, hjust = 1))
步骤3:绘制每日样本占比堆叠图
将position设为"fill"即可实现占比模式,逻辑与计数图一致:
合并分组的占比图
ggplot(sens_df, aes(x = Date, fill = interaction(Organism, Antibiotic, Resistance))) + geom_bar(stat = "count", position = "fill") + labs(title = "每日样本耐药性占比(按微生物+抗生素分组)", x = "日期", y = "占比", fill = "分组(微生物+抗生素+耐药性)") + scale_fill_brewer(palette = "Set3") + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + scale_y_continuous(labels = scales::percent)
分面版本的占比图
ggplot(sens_df, aes(x = Date, fill = interaction(Antibiotic, Resistance))) + geom_bar(stat = "count", position = "fill") + facet_wrap(~Organism) + labs(title = "每日样本耐药性占比(按微生物分面)", x = "日期", y = "占比", fill = "抗生素+耐药性") + scale_fill_brewer(palette = "Set3") + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + scale_y_continuous(labels = scales::percent)
优化图例显示
如果觉得组合后的分组名称过长,可提前在数据中创建新列:
sens_df <- sens_df %>% mutate(Group = paste(Organism, Antibiotic, Resistance, sep = " - "))
之后直接在aes(fill = Group)中使用该列即可。
内容的提问来源于stack exchange,提问作者code_rookie
相关产品推荐
相关产品推荐

