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

使用R的ggplot绘制按微生物与抗生素分组的循环堆叠条形图

用ggplot绘制按微生物和抗生素分组的堆叠条形图

问题背景

我正在尝试用R的ggplot绘制堆叠条形图,现有如下数据框:

样本(Sample)日期(Date)微生物(Organism)抗生素(Antibiotic)耐药性(Resistance)
101/01/2020E ColiAmoxicillinS
101/01/2020E ColiGentamicinS
101/01/2020E ColiCefalexinR
201/01/2020S aureusAmoxicillinS
201/01/2020S aureusGentamicinS
201/01/2020S aureusCefalexinR
301/01/2020E ColiAmoxicillinS
301/01/2020E ColiGentamicinS
301/01/2020E ColiCefalexinS
402/01/2020S aureusAmoxicillinS
402/01/2020S aureusGentamicinS
402/01/2020S aureusCefalexinR
502/01/2020E coliAmoxicillinR
502/01/2020E coliGentamicinS
502/01/2020E coliCefalexinR
603/01/2020E coliAmoxicillinR
603/01/2020E coliGentamicinR
603/01/2020E coliCefalexinS
704/01/2020E coliAmoxicillinS
704/01/2020E coliGentamicinS
704/01/2020E coliCefalexinS
804/01/2020S aureusAmoxicillinS
804/01/2020S aureusGentamicinS
804/01/2020S aureusCefalexinS
905/01/2020Kleb pneumoAmoxicillinS
905/01/2020Kleb pneumoGentamicinS
905/01/2020Kleb pneumoCefalexinS
1005/01/2020Kleb pneumoAmoxicillinR
1005/01/2020Kleb pneumoGentamicinR
1005/01/2020Kleb pneumoCefalexinR
1105/01/2020E coliAmoxicillinS
1105/01/2020E coliGentamicinS
1105/01/2020E coliCefalexinS
1206/01/2020S aureusAmoxicillinS
1206/01/2020S aureusGentamicinS
1206/01/2020S aureusCefalexinS
1306/01/2020Kleb pneumoAmoxicillinS
1306/01/2020Kleb pneumoGentamicinS
1306/01/2020Kleb pneumoCefalexinS
1406/01/2020Kleb pneumoAmoxicillinR
1406/01/2020Kleb pneumoGentamicinR
1406/01/2020Kleb pneumoCefalexinR

需求说明

需要绘制以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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:50:54