在生命科学研究中,组内和组间柱状图是展示实验数据最常用的可视化方式之一。它不仅能直观呈现Western Blot、RT-qPCR等实验的定量分析结果,更重要的是能清晰展示不同处理组之间的差异程度。通过组内重复和组间比较的统计分析,我们可以准确评估实验数据的可靠性和生物学显著性,为研究结论提供有力支撑。

第一步 加载R包

library(ggplot2)   # 主流绘图R包
library(dplyr)     #数据处理R包
library(readxl)    #读取excel数据R包

第二步 加载数据

    本次数据仍然使用以往的数据结构(实验组和对照组,每组3个生物学重复,第一周至第五周的小鼠体重测量数据),我们进行柱状图的统计分析。

## excel数据
data1 <- read_xlsx("Mmu data.xlsx")
## 当然有多个sheet时可以自定义sheet读取
data1 <- read_xlsx("Mmu data.xlsx",sheet = "Sheet1")  # 注意Sheet中S的大写!!!
data1[1:12,]
## # A tibble: 12 × 4
##    Group   Order Time  Value
##    <chr>   <dbl> <chr> <dbl>
##  1 Control     1 D0W    19.7
##  2 Control     2 D0W    20.1
##  3 Control     3 D0W    21.5
##  4 Test        1 D0W    20.7
##  5 Test        2 D0W    21.8
##  6 Test        3 D0W    21.9
##  7 Control     1 D1W    20.7
##  8 Control     2 D1W    21.5
##  9 Control     3 D1W    22.4
## 10 Test        1 D1W    21.3
## 11 Test        2 D1W    20.2
## 12 Test        3 D1W    19.6

第三步 不限定顺序,直接作图

    为了让大家理解这个限定顺序的重要性,我们来演示一下:
    我们把当前的数据中”D5W”分组修改为”C5W”.

## 数据转换一下
data2 <- data1
## 更换分组名称
data2[data2$Time=="D5W",]$Time <- "C5W"
table(data1$Time)
## 
## D0W D1W D2W D3W D4W D5W 
##   6   6   6   6   6   6
table(data2$Time)
## 
## C5W D0W D1W D2W D3W D4W 
##   6   6   6   6   6   6

    此时,我们发现原来的第五周就跑到最前面去了,此时R语言会自己默认字母的顺序对图形进行了二次排序。此时,如果我们作图,会出现顺序颠倒的情况。

第四步 计算汇总数据

# 计算每组的均值和标准误
summary_data <- data2 %>%
  group_by(Group, Time) %>%
  summarise(mean_value = mean(Value),
            se = sd(Value) / sqrt(n()),
            .groups = 'drop')

第五步 可视化

# 创建分组柱状图
ggplot(summary_data, aes(x = Time, y = mean_value, fill = Group)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  geom_errorbar(aes(ymin = mean_value - se, 
                    ymax = mean_value + se),
                position = position_dodge(width = 0.8),
                width = 0.25) +
  # 自定义主题和颜色
  scale_fill_manual(values = c("Control" = "gray", "Test" = "black")) +
  theme_classic() +
  # 添加标签
  labs(title = "Group Comparison Over Time",
       x = "Time Point",
       y = "Value (Mean ± SE)") +
  # 优化主题设置
  theme(plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
        axis.title = element_text(size = 12),
        axis.text = element_text(size = 10),
        legend.title = element_text(size = 12),
        legend.text = element_text(size = 10),
        legend.position = "top")

### 第六步 输出统计值:

# 如果需要进行统计检验
# 执行双因素方差分析
aov_result <- aov(Value ~ Group * Time, data = data1)
summary(aov_result)
##             Df Sum Sq Mean Sq F value   Pr(>F)    
## Group        1 111.27  111.27  183.20 9.95e-13 ***
## Time         5  65.90   13.18   21.70 3.44e-08 ***
## Group:Time   5  70.35   14.07   23.17 1.83e-08 ***
## Residuals   24  14.58    0.61                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 如果需要进行组间比较
# 使用 TukeyHSD
tukey_result <- TukeyHSD(aov_result)
print(tukey_result)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = Value ~ Group * Time, data = data1)
## 
## $Group
##                   diff      lwr       upr p adj
## Test-Control -3.516111 -4.05226 -2.979962     0
## 
## $Time
##               diff        lwr      upr     p adj
## D1W-D0W -0.0300000 -1.4211940 1.361194 0.9999998
## D2W-D0W  1.6550000  0.2638060 3.046194 0.0133117
## D3W-D0W  1.7833333  0.3921393 3.174527 0.0067648
## D4W-D0W  2.7316667  1.3404727 4.122861 0.0000384
## D5W-D0W  3.7116667  2.3204727 5.102861 0.0000003
## D2W-D1W  1.6850000  0.2938060 3.076194 0.0113805
## D3W-D1W  1.8133333  0.4221393 3.204527 0.0057623
## D4W-D1W  2.7616667  1.3704727 4.152861 0.0000327
## D5W-D1W  3.7416667  2.3504727 5.132861 0.0000002
## D3W-D2W  0.1283333 -1.2628607 1.519527 0.9997097
## D4W-D2W  1.0766667 -0.3145273 2.467861 0.1983241
## D5W-D2W  2.0566667  0.6654727 3.447861 0.0015385
## D4W-D3W  0.9483333 -0.4428607 2.339527 0.3167581
## D5W-D3W  1.9283333  0.5371393 3.319527 0.0030983
## D5W-D4W  0.9800000 -0.4111940 2.371194 0.2839480
## 
## $`Group:Time`
##                                  diff        lwr        upr     p adj
## Test:D0W-Control:D0W     1.060000e+00 -1.2343199  3.3543199 0.8664803
## Control:D1W-Control:D0W  1.076667e+00 -1.2176532  3.3709865 0.8550737
## Test:D1W-Control:D0W    -7.666667e-02 -2.3709865  2.2176532 1.0000000
## Control:D2W-Control:D0W  3.640000e+00  1.3456801  5.9343199 0.0003454
## Test:D2W-Control:D0W     7.300000e-01 -1.5643199  3.0243199 0.9885072
## Control:D3W-Control:D0W  4.916667e+00  2.6223468  7.2109865 0.0000033
## Test:D3W-Control:D0W    -2.900000e-01 -2.5843199  2.0043199 0.9999980
## Control:D4W-Control:D0W  6.523333e+00  4.2290135  8.8176532 0.0000000
## Test:D4W-Control:D0W     3.552714e-15 -2.2943199  2.2943199 1.0000000
## Control:D5W-Control:D0W  7.423333e+00  5.1290135  9.7176532 0.0000000
## Test:D5W-Control:D0W     1.060000e+00 -1.2343199  3.3543199 0.8664803
## Control:D1W-Test:D0W     1.666667e-02 -2.2776532  2.3109865 1.0000000
## Test:D1W-Test:D0W       -1.136667e+00 -3.4309865  1.1576532 0.8100076
## Control:D2W-Test:D0W     2.580000e+00  0.2856801  4.8743199 0.0183862
## Test:D2W-Test:D0W       -3.300000e-01 -2.6243199  1.9643199 0.9999923
## Control:D3W-Test:D0W     3.856667e+00  1.5623468  6.1509865 0.0001527
## Test:D3W-Test:D0W       -1.350000e+00 -3.6443199  0.9443199 0.6138559
## Control:D4W-Test:D0W     5.463333e+00  3.1690135  7.7576532 0.0000005
## Test:D4W-Test:D0W       -1.060000e+00 -3.3543199  1.2343199 0.8664803
## Control:D5W-Test:D0W     6.363333e+00  4.0690135  8.6576532 0.0000000
## Test:D5W-Test:D0W       -3.552714e-15 -2.2943199  2.2943199 1.0000000
## Test:D1W-Control:D1W    -1.153333e+00 -3.4476532  1.1409865 0.7964601
## Control:D2W-Control:D1W  2.563333e+00  0.2690135  4.8576532 0.0195219
## Test:D2W-Control:D1W    -3.466667e-01 -2.6409865  1.9476532 0.9999873
## Control:D3W-Control:D1W  3.840000e+00  1.5456801  6.1343199 0.0001626
## Test:D3W-Control:D1W    -1.366667e+00 -3.6609865  0.9276532 0.5973621
## Control:D4W-Control:D1W  5.446667e+00  3.1523468  7.7409865 0.0000005
## Test:D4W-Control:D1W    -1.076667e+00 -3.3709865  1.2176532 0.8550737
## Control:D5W-Control:D1W  6.346667e+00  4.0523468  8.6409865 0.0000000
## Test:D5W-Control:D1W    -1.666667e-02 -2.3109865  2.2776532 1.0000000
## Control:D2W-Test:D1W     3.716667e+00  1.4223468  6.0109865 0.0002586
## Test:D2W-Test:D1W        8.066667e-01 -1.4876532  3.1009865 0.9758622
## Control:D3W-Test:D1W     4.993333e+00  2.6990135  7.2876532 0.0000025
## Test:D3W-Test:D1W       -2.133333e-01 -2.5076532  2.0809865 0.9999999
## Control:D4W-Test:D1W     6.600000e+00  4.3056801  8.8943199 0.0000000
## Test:D4W-Test:D1W        7.666667e-02 -2.2176532  2.3709865 1.0000000
## Control:D5W-Test:D1W     7.500000e+00  5.2056801  9.7943199 0.0000000
## Test:D5W-Test:D1W        1.136667e+00 -1.1576532  3.4309865 0.8100076
## Test:D2W-Control:D2W    -2.910000e+00 -5.2043199 -0.6156801 0.0054620
## Control:D3W-Control:D2W  1.276667e+00 -1.0176532  3.5709865 0.6854679
## Test:D3W-Control:D2W    -3.930000e+00 -6.2243199 -1.6356801 0.0001161
## Control:D4W-Control:D2W  2.883333e+00  0.5890135  5.1776532 0.0060339
## Test:D4W-Control:D2W    -3.640000e+00 -5.9343199 -1.3456801 0.0003454
## Control:D5W-Control:D2W  3.783333e+00  1.4890135  6.0776532 0.0002012
## Test:D5W-Control:D2W    -2.580000e+00 -4.8743199 -0.2856801 0.0183862
## Control:D3W-Test:D2W     4.186667e+00  1.8923468  6.4809865 0.0000448
## Test:D3W-Test:D2W       -1.020000e+00 -3.3143199  1.2743199 0.8917475
## Control:D4W-Test:D2W     5.793333e+00  3.4990135  8.0876532 0.0000002
## Test:D4W-Test:D2W       -7.300000e-01 -3.0243199  1.5643199 0.9885072
## Control:D5W-Test:D2W     6.693333e+00  4.3990135  8.9876532 0.0000000
## Test:D5W-Test:D2W        3.300000e-01 -1.9643199  2.6243199 0.9999923
## Test:D3W-Control:D3W    -5.206667e+00 -7.5009865 -2.9123468 0.0000012
## Control:D4W-Control:D3W  1.606667e+00 -0.6876532  3.9009865 0.3713294
## Test:D4W-Control:D3W    -4.916667e+00 -7.2109865 -2.6223468 0.0000033
## Control:D5W-Control:D3W  2.506667e+00  0.2123468  4.8009865 0.0239040
## Test:D5W-Control:D3W    -3.856667e+00 -6.1509865 -1.5623468 0.0001527
## Control:D4W-Test:D3W     6.813333e+00  4.5190135  9.1076532 0.0000000
## Test:D4W-Test:D3W        2.900000e-01 -2.0043199  2.5843199 0.9999980
## Control:D5W-Test:D3W     7.713333e+00  5.4190135 10.0076532 0.0000000
## Test:D5W-Test:D3W        1.350000e+00 -0.9443199  3.6443199 0.6138559
## Test:D4W-Control:D4W    -6.523333e+00 -8.8176532 -4.2290135 0.0000000
## Control:D5W-Control:D4W  9.000000e-01 -1.3943199  3.1943199 0.9491313
## Test:D5W-Control:D4W    -5.463333e+00 -7.7576532 -3.1690135 0.0000005
## Control:D5W-Test:D4W     7.423333e+00  5.1290135  9.7176532 0.0000000
## Test:D5W-Test:D4W        1.060000e+00 -1.2343199  3.3543199 0.8664803
## Test:D5W-Control:D5W    -6.363333e+00 -8.6576532 -4.0690135 0.0000000

    我们限定一下顺序:

# 设置Week的顺序
summary_data$Time <- factor(summary_data$Time, 
                            levels = c("D0W", "D1W", "D2W", "D3W", "D4W","C5W"))

    重新作图:

# 创建分组柱状图
ggplot(summary_data, aes(x = Time, y = mean_value, fill = Group)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  geom_errorbar(aes(ymin = mean_value - se, 
                    ymax = mean_value + se),
                position = position_dodge(width = 0.8),
                width = 0.25) +
  # 自定义主题和颜色
  scale_fill_manual(values = c("Control" = "gray", "Test" = "black")) +
  theme_classic() +
  # 添加标签
  labs(title = "Group Comparison Over Time",
       x = "Time Point",
       y = "Value (Mean ± SE)") +
  # 优化主题设置
  theme(plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
        axis.title = element_text(size = 12),
        axis.text = element_text(size = 10),
        legend.title = element_text(size = 12),
        legend.text = element_text(size = 10),
        legend.position = "top")

## 也可以添加趋势线,更加突出沿着时间节点的趋势变化: # 创建分组柱状图

ggplot(summary_data, aes(x = Time, y = mean_value, fill = Group, group = Group)) +
  # 柱状图层
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
  # 误差线层
  geom_errorbar(aes(ymin = mean_value - se, 
                    ymax = mean_value + se),
                position = position_dodge(width = 0.8),
                width = 0.25) +
  # 添加虚线趋势线
  geom_line(aes(color = Group), 
            position = position_dodge(width = 0.8),
            linetype = "dashed",
            size = 0.8) +
  # 自定义主题和颜色
  scale_fill_manual(values = c("Control" = "gray", "Test" = "black")) +
  scale_color_manual(values = c("Control" = "gray", "Test" = "black")) +
  theme_classic() +
  # 添加标签
  labs(title = "Group Comparison Over Time",
       x = "Time Point",
       y = "Value (Mean ± SE)") +
  # 优化主题设置
  theme(plot.title = element_text(size = 14, 
                                  face = "bold", hjust = 0.5),
        axis.title = element_text(size = 12),
        axis.text = element_text(size = 10),
        legend.title = element_text(size = 12),
        legend.text = element_text(size = 10),
        legend.position = "top")