专注收集和自写可发表的科研图形的数据和代码分享,该系列的数据均可从以下链接下载:
百度云盘链接: https://pan.baidu.com/s/1M4vgU1ls0tilt0oSwFbqYQ
提取码: 请关注WX公zhong号 生信学习者 后台发送 科研绘图 获取提取码
介绍
分组柱状图(Grouped Bar Chart)是一种数据可视化图表,用于比较不同类别(分组)内各子类别(子组)的数值。在分组柱状图中,每个分组有一组并列的柱子,每个柱子代表一个子组的数值,不同的分组用不同的列来表示。
特点:
并列柱子:每个分组内的柱子是并列的,便于在同一分组内比较不同子组。
分组比较:可以直观地比较不同分组之间的数值大小。
多变量展示:同时展示分组和子组两个层次的变量。
适合情况:
多类别比较:当你需要比较两个或多个类别(如性别、年龄组、地区等)内不同子类别的数据时。
层次化数据:数据具有层次结构,例如,首先按国家分组,然后在国家内部按城市或州进行分组。
展示相对差异:当需要展示不同子组在相同分组内的相对大小或比例时。
避免数据重叠:在某些情况下,使用堆叠柱状图可能导致底层数据难以解读,分组柱状图可以避免这个问题。
强调分组内比较:如果你更关注于分组内部的比较,而不是分组之间的比较。
有限的分组数量:当分组数量不是很多时,分组柱状图可以清晰地展示每个分组的数据,如果分组数量太多,图表可能会变得拥挤。
数据量适中:当每个分组内的子组数量适中,不会使图表过于复杂或难以解读。
加载R包
knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)
library(tidyverse)
library(ggpubr)
library(plyr)
library(ggsignif)
library(ggprism)
# rm(list = ls())
options(stringsAsFactors = F)
# group & color
dose_names <- c("0.5", "1", "2")
dose_colors <- c("#0073C2FF", "#EFC000FF", "#CD534CFF")
supp_names <- c("OJ", "VC")
supp_colors <- c('#999999','#E69F00')
导入数据
data("ToothGrowth")
head(ToothGrowth)
len | supp | dose |
---|---|---|
4.2 | VC | 0.5 |
11.5 | VC | 0.5 |
7.3 | VC | 0.5 |
5.8 | VC | 0.5 |
6.4 | VC | 0.5 |
10.0 | VC | 0.5 |
准备数据
筛选画图数据
plotdata <- ToothGrowth |>
dplyr::mutate(dose = factor(as.character(dose), levels = dose_names),
supp = factor(supp, levels = supp_names)) |>
dplyr::rename(Group = dose,
Subgroup = supp,
Index = len) |>
dplyr::select(Group, Subgroup, Index)
head(plotdata)
Group | Subgroup | Index |
---|---|---|
0.5 | VC | 4.2 |
0.5 | VC | 11.5 |
0.5 | VC | 7.3 |
0.5 | VC | 5.8 |
0.5 | VC | 6.4 |
0.5 | VC | 10.0 |
通过
data_summary
函数计算每个分组的mean & sd & se
data_summary <- function(data, varname, groupnames){
summary_func <- function(x, col) {
mean_value <- mean(x[[col]], na.rm = TRUE)
sd_value <- sd(x[[col]], na.rm = TRUE)
length_n <- length(x[[col]])
# standard error= standard deviation/squareroot(n)
se_value <- sd_value / sqrt(length_n)
return(c(mean = mean_value, sd = sd_value, se = se_value))
}
data_sum <- ddply(data, groupnames, .fun=summary_func, varname)
colnames(data_sum)[which(colnames(data_sum) == "mean")] <- varname
return(data_sum)
}
plotdata2 <- data_summary(
data = plotdata,
varname = "Index",
groupnames = c("Group", "Subgroup"))
head(plotdata2)
Group | Subgroup | Index | sd | se |
---|---|---|---|---|
0.5 | OJ | 13.23 | 4.459709 | 1.4102837 |
0.5 | VC | 7.98 | 2.746634 | 0.8685620 |
1 | OJ | 22.70 | 3.910953 | 1.2367520 |
1 | VC | 16.77 | 2.515309 | 0.7954104 |
2 | OJ | 26.06 | 2.655058 | 0.8396031 |
2 | VC | 26.14 | 4.797731 | 1.5171757 |
计算组间差异P值
df_p_val <- plotdata %>%
rstatix::group_by(Group) %>%
rstatix::t_test(Index ~ Subgroup) %>%
rstatix::adjust_pvalue(p.col = "p", method = "bonferroni") %>%
rstatix::add_significance(p.col = "p.adj") %>%
rstatix::add_xy_position(x = "Group", dodge = 0.8) %>% # important for positioning!
dplyr::mutate(p.adj = round(p.adj, 3))
head(df_p_val)
Group | .y. | group1 | group2 | n1 | n2 | statistic | df | p | p.adj |
---|---|---|---|---|---|---|---|---|---|
0.5 | Index | OJ | VC | 10 | 10 | 3.1697328 | 14.96875 | 0.00636 | 0.019 |
1 | Index | OJ | VC | 10 | 10 | 4.0327696 | 15.35767 | 0.00104 | 0.003 |
2 | Index | OJ | VC | 10 | 10 | -0.0461361 | 14.03982 | 0.96400 | 1.000 |
画图
分组柱状图展示不同分组的比较结果,以下是代码解释:
ggplot(data = plotdata2, aes(x = Group, y = Index))
: 初始化ggplot
对象,使用plotdata2
作为数据源,将Group
映射到x轴,Index
映射到y轴。geom_bar(aes(fill = Subgroup), stat = "identity", ...)
: 添加条形图层,使用aes(fill = Subgroup)
将Subgroup
映射到条形的填充颜色,stat = "identity"
表示条形的高度由数据中的Index
确定,position_dodge()
确保不同子组的条形在同一分组内并排显示。geom_errorbar(...)
: 添加误差条图层,显示数据的标准差范围,aes(color = Subgroup)
将Subgroup
映射到误差条的颜色,position_dodge()
调整误差条的位置以适应条形的宽度。ggprism::add_pvalue(...)
: 使用ggprism
包的add_pvalue
函数添加显著性p值标签,xmin
和xmax
定义了标签的位置,label
定义了标签的格式。geom_point(...)
: 在条形图上添加点图层,使用plotdata
数据集,点的位置由Group
和Index
确定,shape
映射到点的形状,position_jitterdodge
添加抖动和偏移以避免点的重叠。labs(x = "")
: 设置x轴标签,这里将其设置为空字符串。scale_y_continuous(...)
: 设置y轴的比例尺,guide = "prism_minor"
指定y轴的次要刻度,minor_breaks
设置次要刻度的间隔,limits
设置y轴的范围,expand
调整y轴的范围,留出一些空间。scale_fill_prism()
,scale_color_prism()
,scale_shape_prism()
: 使用ggprism
包提供的尺度函数来设置填充颜色、边框颜色和点形状。guides(color = "none", shape = "none")
: 设置图例,这里将颜色和形状的图例设置为不显示。theme_prism()
: 应用ggprism
包的主题样式。theme(...)
: 自定义图形的主题样式,包括轴标题、轴文本的大小、颜色和字体,以及图例的位置。
pl_prism <- ggplot(data = plotdata2, aes(x = Group, y = Index)) +
geom_bar(aes(fill = Subgroup), stat = "identity",
color = "white", position = position_dodge()) +
geom_errorbar(aes(color = Subgroup,
ymin = Index - sd, ymax = Index + sd),
width = 0.2, position = position_dodge(width = 0.9),
size = 1) +
ggprism::add_pvalue(data = df_p_val,
xmin = "xmin",
xmax = "xmax",
label = "p = {p.adj}",
tip.length = 0) +
geom_point(data = plotdata,
aes(x = Group, y = Index, shape = Subgroup),
position = position_jitterdodge(jitter.width = 0.5,
dodge.width = 0.7),
size = 2, show.legend = FALSE) +
labs(x = "") +
scale_y_continuous(guide = "prism_minor", # prism_offset
minor_breaks = seq(0, 40, 2),
limits = c(0, 40),
expand = expansion(mult = c(0, 0.1))) +
scale_fill_prism() +
scale_color_prism() +
scale_shape_prism() +
guides(color = "none", shape = "none") +
theme_prism() +
theme(axis.title = element_text(size = 12, color = "black", face = "bold"),
axis.text = element_text(size = 10, color = "black"),
text = element_text(size = 9, color = "black"),
legend.position = c(0.15, 0.85))
pl_prism
结果:不同水平下,内部分组的Index
指数的差异结果。
如果大家有任何问题,欢迎留言沟通交流