科研绘图系列:R语言实验结果组图(linechart + barplot)

文摘   2024-07-06 09:19   广东  

专注收集和自写可发表的科研图形的数据和代码分享,该系列的数据均可从以下链接下载:

百度云盘链接: https://pan.baidu.com/s/1M4vgU1ls0tilt0oSwFbqYQ
提取码: 请关注WX公zhong号 生信学习者 后台发送 科研绘图 获取提取码

介绍

实验结果的多样性意味着每个结果都可能揭示研究的不同方面或角度。在科学研究和数据分析中,通常我们会收集一系列数据点,每个数据点都对应着实验的一个特定变量或条件。为了全面理解这些数据,我们可能会采用多种可视化技术来展示它们。

将多个结果分别可视化,可以让我们更清晰地看到每个结果的独特特征和趋势。例如,折线图通常用于展示数据随时间或其他有序类别变化的趋势,而条形图则更适合比较不同类别之间的数值差异。

在本教程中,我们采用了两种主要的图表类型来分别展示实验的不同结果:

  1. 折线图:这种图表通过折线连接各个数据点,非常适合用来展示连续数据随时间或其他有序变量的变化趋势。折线图可以帮助我们识别数据的上升、下降、波动或平稳等模式。

  2. 条形图:条形图通过不同高度的条形来表示数据的大小,非常适合用来比较不同类别或组别的数值。条形的高度直接对应数据值的大小,使得比较直观且易于理解。

将这些单独的图表组合成一个图形,可以提供一个综合的视角,使我们能够同时观察和比较不同结果之间的关系和相互作用。这种综合图表不仅能够增强我们对数据的理解,还能够在报告或演示中有效地传达复杂的概念和发现。通过这种方式,我们能够确保每个单独的可视化结果都服务于展示实验的整体目的和结论。

加载R包

knitr::opts_chunk$set(message = FALSE, warning = FALSE)
library(tidyverse)
library(patchwork)
library(reshape2)

rm(list = ls())
options(stringsAsFactors = F)

导入数据

百度云盘链接: https://pan.baidu.com/s/1M4vgU1ls0tilt0oSwFbqYQ
提取码: 请关注WX公zhong号 生信学习者 后台发送 科研绘图 获取提取码

data <- read.csv("./inputdata/12-trialplot.csv")

head(data)

treatDayvalue1value2value3Non_SMKSMKNon_SMK.abxSMK.abx
1Non_SMK00.00.00.020010013010
2Non_SMK76.76.86.924012021020
3Non_SMK1414.014.214.225512530045
4Non_SMK2115.617.719.9260145285100
5Non_SMK2824.025.921.82604530511
6Non_SMK3530.028.432.527550330180

绘制折线图

实验结果组图由上下两部分组成,上图是条形图,下图是折线图,先绘制折线图。

准备数据

  • 准备绘制数据

  • 准备绘制函数

#取出前5列的折线图数据,然后根据treat、Day合并数值列:
data1 <- data[, c(1:5)] %>%
melt(id = c('treat', 'Day'))

#设置绘制误差棒errorbar时用到的函数:
topbar <- function(x) {
return(mean(x)+sd(x)/sqrt(length(x))) #误差采用了mean+-sem
}
bottombar <- function(x){
return(mean(x)-sd(x)/sqrt(length(x)))
}

绘图折线图主图

先绘制实验结果的折线图主图,下列是代码解释:

  1. ggplot(data1, aes(Day, value, color = treat)):初始化ggplot对象,使用数据集data1aes()函数定义了数据的美学映射,其中Day映射到x轴,value映射到y轴,treat映射到颜色。

  2. geom_rect(...):添加矩形图层,用于在图表中高亮显示特定区域。这里xmin = 21xmax = 40定义了矩形的左右边界,ymin = (-Inf)ymax = Inf表示矩形覆盖整个y轴的范围。fillcolor设置了矩形的填充和边框颜色。

  3. geom_vline(xintercept = 21, linetype = 2, cex = 1.2):添加垂直虚线图层,表示x轴上的特定点。这里xintercept = 21定义了虚线的位置,linetype = 2设置了线型为虚线,cex调整了线条的粗细。

  4. stat_summary(geom = 'line', fun = 'mean', cex = 2.5):使用stat_summary函数添加统计摘要图层,这里geom = 'line'指定了图层类型为折线,fun = 'mean'表示使用均值作为统计摘要,cex调整了线条的粗细。

  5. stat_summary(...):再次使用stat_summary函数添加误差条图层,aes(color = treat)指定了颜色映射,geom = 'errorbar'指定了图层类型为误差条。fun.minfun.max定义了误差条的最小和最大值函数,这里使用bottombartopbar函数,可能是自定义函数,用于计算误差条的上下界。width设置了误差条的宽度,cex调整了误差条的粗细。

  6. stat_summary(...):第三次使用stat_summary函数添加点图层,aes(fill = treat)指定了填充颜色映射,geom = 'point'指定了图层类型为点。fun = 'mean'表示使用均值,size设置了点的大小,pch设置了点的类型,color设置了点的边框颜色。

  7. theme_classic(base_size = 15):应用经典主题,并设置基础字体大小为15。

  8. theme(legend.position = 'none'):自定义主题设置,这里将图例位置设置为'none',即不显示图例。

p0 <- ggplot(data1, aes(Day, value, color = treat))+
geom_rect(aes(xmin = 21, xmax = 40, ymin = (-Inf), ymax = Inf),
fill = 'grey90', color = 'grey90')+
geom_vline(xintercept = 21, linetype = 2, cex = 1.2)+
stat_summary(geom = 'line', fun = 'mean', cex = 2.5)+
stat_summary(aes(color = treat), geom = 'errorbar',
fun.min = bottombar, fun.max = topbar,
width = 1, cex = 0.8)+
stat_summary(aes(fill = treat), geom = 'point', fun = 'mean',
size = 5, pch = 21, color = 'black')+
theme_classic(base_size = 15)+
theme(legend.position = 'none')

p0

添加折线图细节

添加组间检验差异结果到折线图中,下列是代码解释:

  1. p0:之前创建的ggplot对象。

  2. scale_color_manual(...)scale_fill_manual(...):这两行代码用于手动设置图表中的颜色比例尺。values参数定义了不同分类对应的颜色,这里为四种不同的颜色代码。

  3. scale_y_continuous(...):设置y轴的连续比例尺。breaks参数定义了y轴的刻度位置,这里设置为从0到60,每20一个刻度。expand = c(0, 0)确保了y轴的刻度不会超出数据范围。

  4. scale_x_continuous(...):设置x轴的连续比例尺。与y轴类似,这里设置x轴的刻度从0到40,每10一个刻度,并且刻度不会超出数据范围。

  5. labs(y = 'Weight change(%)'):设置y轴的标签为"Weight change(%)"。

  6. theme(...):自定义图表的主题样式。这里设置了轴线的大小、颜色和刻度线的大小及颜色。

  7. annotate(geom = 'segment', ...):使用annotate函数添加线段注释。第一个annotate函数在x = 36.2的位置添加了一条垂直线段,从y = 18到y = 26。cex参数调整了线段的粗细。

  8. annotate(geom = 'text', ...):使用annotate函数添加文本注释。这里在x = 37.5,y = 22的位置添加了文本"***",size设置了文本的大小,angle = 90使文本旋转90度。

  9. 第二个annotate(geom = 'segment', ...):在x = 38的位置添加了另一条垂直线段,从y = 18到y = 40。

  10. 第二个annotate(geom = 'text', ...):在x = 39.5,y = 29的位置添加了文本"****",文本大小和旋转角度与上一个文本注释相同。

p1 <- p0 +
scale_color_manual(values = c('#5494cc', '#0d898a', '#e18283', '#f9cc52'))+
scale_fill_manual(values = c('#5494cc', '#0d898a', '#e18283', '#f9cc52'))+
scale_y_continuous(breaks = seq(0, 60, 20), expand = c(0, 0))+
scale_x_continuous(breaks = seq(0, 40, 10), expand = c(0, 0))+
labs(y = 'Weight change(%)')+
theme(axis.line = element_line(size = 1),
axis.text = element_text(color = 'black'),
axis.ticks = element_line(size = 1, color = 'black'))+
annotate(geom = 'segment', x = 36.2, xend = 36.2, y = 18, yend = 26, cex = 1.2)+
annotate(geom = 'text', label = '***', x = 37.5, y = 22, size = 7, angle = 90)+
annotate(geom = 'segment', x = 38, xend = 38, y = 18, yend = 40, cex = 1.2)+
annotate(geom = 'text', label = '****', x = 39.5, y = 29, size = 7, angle = 90)

p1

添加折线图的图例

不同的折线表示不同的分组,将分组信息添加进折线图,下列是代码的解释:

  1. p1:之前创建的ggplot对象。

  2. coord_cartesian(clip = 'off', ylim = c(0, 60), xlim = c(0, 40)):设置坐标轴的范围,并关闭坐标轴之外的裁剪。这意味着即使图形元素超出了坐标轴范围,它们也会被显示出来。ylimxlim分别设置了y轴和x轴的范围。

  3. theme(plot.margin = margin(1.5, 0.5, 0.5, 0.5, 'cm')):设置图表的边距。margin函数定义了图表的上、右、下、左边距的大小,单位为厘米。

  4. geom_rect(...):这四行代码使用geom_rect函数添加矩形图层,每个矩形对应一个美学映射,定义了矩形的左下角和右上角的位置(xminxmaxyminymax),填充颜色(fill)和边框颜色(color)。这些矩形可能用于在图表上高亮显示特定的区域或时间段。

  5. annotate('text', ...):这四行代码使用annotate函数添加文本注释。xy参数定义了文本的位置,label参数定义了文本内容,size参数定义了文本的大小。这些文本注释可能用于解释图表中的矩形区域代表的组别或条件。

linechart <- p1+
coord_cartesian(clip = 'off', ylim = c(0, 60), xlim = c(0, 40))+
theme(plot.margin = margin(1.5, 0.5, 0.5, 0.5, 'cm'))+
geom_rect(aes(xmin = 0, xmax = 3, ymin = 63, ymax = 65), fill = '#5494cc', color = 'black')+
geom_rect(aes(xmin = 10, xmax = 13, ymin = 63, ymax = 65), fill = '#0d898a', color = 'black')+
geom_rect(aes(xmin = 20, xmax = 23, ymin = 63, ymax = 65), fill = '#e18283', color = 'black')+
geom_rect(aes(xmin = 30, xmax = 33, ymin = 63, ymax = 65), fill = '#f9cc52', color = 'black')+
annotate('text', x = 6, y = 64, label = 'Non-SMK', size = 4)+
annotate('text', x = 15.2, y = 64, label = 'SMK', size = 4)+
annotate('text', x = 26.4, y = 64, label = 'Non-SMK+\nabx', size = 4)+
annotate('text', x = 36, y = 64, label = 'SMK+abx', size = 4)

linechart

绘制条形图

实验结果组图由上下两部分组成,上图是条形图,下图是折线图,先绘制折线图后绘制条形图。条形图又由左右两个条形图组成,先绘制左边再绘制右边图。

准备数据

  • 准备绘制左侧iAUC: Exposure条形图数据,不同治疗方式的效果

data2 <- data[, 6:9] %>% 
gather(key = treat)

head(data2)

treatvalue

1Non_SMK200

2Non_SMK240

3Non_SMK255

4Non_SMK260

5Non_SMK260

6Non_SMK275

  • 准备绘制右侧iAUC: Cessation条形图数据,不同治疗方式的效果

data3 <- data[, 10:13] %>% 
gather(key = treat)

head(data3)

treatvalue

1Non_SMK.190

2Non_SMK.1120

3Non_SMK.160

4Non_SMK.150

5Non_SMK.140

6Non_SMK.130

左边条形图

左侧iAUC: Exposure条形图表示四个分组的iAUC表达情况,下列是代码解释:

  1. ggplot(data2, aes(...)):初始化ggplot对象,使用数据集data2aes()函数定义了数据的美学映射,其中factor(treat, levels = c(...))treat变量转换为因子(categorical variable),并指定了因子的水平顺序。

  2. stat_summary(...):添加统计摘要图层,使用geom = 'bar'绘制条形图表示均值,fun = 'mean'指定了使用的统计函数为均值计算。

  3. stat_summary(...):再次添加统计摘要图层,这次使用geom = 'errorbar'绘制误差条,fun.minfun.max指定了最小和最大值的计算函数,这里可能是自定义函数bottombartopbar

  4. geom_jitter(...):添加散点图层,使用抖动(jitter)来避免数据点重叠,aes(color = ...)定义了点的颜色映射。

  5. scale_color_manual(...):手动设置颜色比例尺,定义了不同处理组的颜色。

  6. labs(x = NULL, y = NULL):设置x轴和y轴的标签为NULL,即不显示标签。

  7. scale_y_continuous(...):设置y轴的连续比例尺,limits定义了y轴的范围,expand确保了y轴的范围不会超出数据范围。

  8. geom_hline(...):添加水平线图层,yintercept = 0指定了水平线的位置。

  9. theme_classic(...):应用经典主题,并设置基础字体大小。

  10. theme(...):自定义图表的主题样式,包括隐藏y轴的刻度和文本,设置图例位置为'none',以及调整轴线和刻度线的大小和颜色。

  11. coord_flip():翻转坐标轴,使得x轴和y轴互换位置。

  12. annotate(geom = 'segment', ...):使用annotate函数添加线段注释,指定了线段的起点和终点。

  13. annotate(geom = 'text', ...):使用annotate函数添加文本注释,指定了文本的位置、标签、大小和旋转角度。

leftchart <- ggplot(data2,aes(factor(treat,levels = c('SMK.abx','Non_SMK.abx','SMK','Non_SMK')),
value))+
stat_summary(geom = 'bar', fun = 'mean', fill = 'white', color = 'black', width = 0.7, cex = 1)+
stat_summary(geom = 'errorbar',
fun.min = bottombar, fun.max = topbar,
width = 0.3, cex = 0.8, color = 'black')+
geom_jitter(aes(color = factor(treat, levels = c('SMK.abx', 'Non_SMK.abx', 'SMK', 'Non_SMK'))),
width = 0.1, size = 1.5)+
scale_color_manual(values = c('#f9cc52', '#0d898a', '#e18283', '#5494cc'))+
labs(x = NULL, y = NULL)+
scale_y_continuous(limits = c(-40, 600), expand = c(0, 0))+
geom_hline(yintercept = 0, cex = 1)+
theme_classic(base_size = 15)+
theme(axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
legend.position = 'none',
axis.line = element_line(size = 1),
axis.text = element_text(color = 'black'),
axis.ticks = element_line(size = 1, color = 'black'))+
coord_flip()+
annotate(geom = 'segment', x = 1, xend = 2, y = 530, yend = 530, cex = 1.2)+
annotate(geom = 'text', label = '****', x = 1.5, y = 570, size = 6, angle = 90)+
annotate(geom = 'segment', x = 3, xend = 4, y = 370, yend = 370, cex = 1.2)+
annotate(geom = 'text', label = '****', x = 3.5, y = 410, size = 6, angle = 90)

leftchart

右边条形图

右侧iAUC: Cessation条形图表示四个分组的iAUC表达情况,下列是代码解释:

  1. ggplot(data3, aes(...)):初始化ggplot对象,使用数据集data3aes()函数定义了数据的美学映射,其中factor(treat, levels = c(...))treat变量转换为因子,并指定了因子的水平顺序。

  2. stat_summary(...):添加统计摘要图层,使用geom = 'bar'绘制条形图表示均值,fun = 'mean'指定了使用的统计函数为均值计算。

  3. stat_summary(...):添加统计摘要图层,使用geom = 'errorbar'绘制误差条,fun.minfun.max指定了最小和最大值的计算函数,这里可能是自定义函数bottombartopbar

  4. geom_jitter(...):添加散点图层,使用抖动(jitter)来避免数据点重叠,aes(color = ...)定义了点的颜色映射。

  5. scale_color_manual(...):手动设置颜色比例尺,定义了不同处理组的颜色。

  6. labs(x = NULL, y = NULL):设置x轴和y轴的标签为NULL,即不显示标签。

  7. scale_y_continuous(...):设置y轴的连续比例尺,limits定义了y轴的范围,expand确保了y轴的范围不会超出数据范围。

  8. geom_hline(...):添加水平线图层,yintercept = 0指定了水平线的位置。

  9. theme_classic(...):应用经典主题,并设置基础字体大小。

  10. theme(...):自定义图表的主题样式,包括隐藏y轴的刻度和文本,设置图例位置为'none',以及调整轴线和刻度线的大小和颜色。plot.backgroundpanel.background设置图表和面板背景为透明。

  11. coord_flip():翻转坐标轴,使得x轴和y轴互换位置。

  12. annotate(geom = 'segment', ...):使用annotate函数添加线段注释,指定了线段的起点和终点。

  13. annotate(geom = 'text', ...):使用annotate函数添加文本注释,指定了文本的位置、标签、大小和旋转角度。

rightchart <- ggplot(data3, aes(factor(treat, levels = c('SMK.abx.1', 'Non_SMK.abx.1', 'SMK.1', 'Non_SMK.1')),
value))+
stat_summary(geom = 'bar', fun = 'mean', fill = 'white', color = 'black', width = 0.7, cex = 1)+
stat_summary(geom = 'errorbar',
fun.min = bottombar, fun.max = topbar,
width = 0.3, cex = 0.8, color = 'black')+
geom_jitter(aes(color = factor(treat, levels = c('SMK.abx.1', 'Non_SMK.abx.1', 'SMK.1', 'Non_SMK.1'))),
width = 0.1, size = 1.5)+
scale_color_manual(values = c('#f9cc52', '#0d898a', '#e18283', '#5494cc'))+
labs(x = NULL, y = NULL)+
scale_y_continuous(limits = c(-40, 500), expand = c(0, 0))+
geom_hline(yintercept = 0, cex = 1)+
theme_classic(base_size = 15)+
theme(axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
legend.position = 'none',
axis.line = element_line(size = 1),
axis.text = element_text(color = 'black'),
axis.ticks = element_line(size = 1, color = 'black'),
plot.background = element_rect(fill = "transparent", colour = NA),
panel.background = element_rect(fill = "transparent", colour = NA))+
coord_flip()+
annotate(geom = 'segment', x = 1, xend = 2, y = 420, yend = 420, cex = 1.2)+
annotate(geom = 'text', label = '****', x = 1.5, y = 460, size = 6, angle = 90)+
annotate(geom = 'segment', x = 3, xend = 4, y = 430, yend = 430, cex = 1.2)+
annotate(geom = 'text', label = '****', x = 3.5, y = 470, size = 6, angle = 90)

rightchart

组图

将折线图和条形图组合起来,以折线图作为骨架,将条形图恰套进折线图。

leftchart_new <- ggplotGrob(leftchart)
rightchart_new <- ggplotGrob(rightchart)

pl_final <- linechart +
annotation_custom(leftchart_new, xmin = 0, xmax = 20.5, ymin = 40, ymax = 57)+
annotation_custom(rightchart_new, xmin = 21, xmax = 39.5, ymin = 40, ymax = 57)+
annotate('text', label = 'iAUC: Exposure', x = 10.5, y = 58.5, size = 7)+
annotate('text', label = 'iAUC: Cessation', x = 31, y = 58.5, size = 7)

pl_final

结果:四组样本在不同时间点的体重变化情况,并伴随着不同处理手段的iAUC的水平变化。

  • 折线图反映了SMKabxweight change的影响;

  • 条形图反映了不处理手段下不同分组的iAUC变化;

  • 同一张图的多张子图表达同一类结果即不同分组在不同处理手段下对样本的weight changeiAUC的影响,这才是可视化的意义,而不是胡乱堆砌不同结果却无法说明同一个结果。

如果大家有任何问题,欢迎留言沟通交流

参考

  • [R语言ggplot2 | 学习Nature文章精美配图 | 折线图 | 条形图 | 误差棒 | 灰色背景 | 图片叠加](https://zhuanlan.zhihu.com/p/457088007)

生信学习者
生信教程分享,专注数据分析和科研绘图方向欢迎大家关注,也可一起探讨生信问题