R语言的主成分分析(PCA)详解和带聚类的PCA图绘制
最近有个老师在整理文章数据,由于分组较多,想展示PCA图,说明不同分组的差异,公司默认给出的PCA图比较朴素,想做的好看一些,怎么来做呢。自然难不倒小编,以下几种展示方法,让文章图表更炫酷(前提是样品多,分组多,如果2组3重复,是不够的)。
在RNA-seq中,主成分分析(PCA)是最常见的多元数据分析类型之一。基因表达定量后获得了各样本中所有基因的表达值信息,随后我们通常会期望比较样本之间在基因表达值的整体相似性或者差异程度。基因数量成千上万,肯定不能对每个基因的表达都作个比较,这时候就要用到“降维”算法,PCA分析因此派上用场。PCA设法将N维(N=基因数量)的表达矩阵降维成只有少数几个主成分的形式,这几个主成分就可以代表所有基因的整体表达格局,进而据此描述样本差异。
例如这是文献中的一些PCA分析图。
PCA图中,如果两个样本间整体基因表达值更为相似,那么它们的距离就接近;反之若整体基因表达值差异很大,则它们的距离就会更远。据此,我们就可以从中评估,不同组间样本的基因表达是否相差更为明显,组内样本的基因表达是否均匀或一致性较高,哪些处理组之间引起了相似的基因表达变化趋势,等等。
本篇教程就让我们来学习如何使用R语言进行PCA分析。示例数据和R代码等,可添加微信公众号”获取。
1 示例数据
“PCA.data.txt”为基因表达值矩阵。其中第一列“ensembl_id”为基因名称,这里以ensembl id作为指代;其余各列为各样本的名称,记录了RNA-seq获得的各基因在各样本中的表达值信息。
“group.txt”则为样本分组文件,记录了样本所属的不同分组。对于示例数据而言,共包含两组,即对照组(control)和处理组(treat),每组各5个样本。
接下来,就以基因表达值矩阵文件作为输入,展示如何进行PCA分析的一般过程。
2 R语言执行主成分分析(PCA)
首先,需要根据基因表达值进行样本间的PCA分析,确定样本在PCA图中的位置。
将上述基因表达值矩阵读入到R中进行计算。R语言中能够执行PCA分析的方法有很多,不过它们的算法都是统一的,随便使用任何一个R包就可以,例如这里选择使用FactoMineR包中的PCA方法。
#读取基因表达值矩阵
#推荐使用 log 转化后的基因表达值,降低不同基因表达水平数量级相差过大的问题
gene <- read.delim('PCA.data.txt', row.names = 1, sep = '\t')
#将基因表达值矩阵作个转置,使行为样本,列为基因
gene <- t(gene)
#我们使用 FactoMineR 包中的方法,实现 PCA 分析和聚类添加
library(FactoMineR)
#样本中基因表达值的 PCA 分析
gene.pca <- PCA(gene, ncp = 2, scale.unit = TRUE, graph = FALSE)
plot(gene.pca) #PCA 简图
这样,PCA分析结果就初步得到了。从结果中我们可以看出,处理组和对照组的基因表达值整体差异还是非常明显的,因为两组的样本能够在PCA图中区分很开。
3 可视化PCA图
上一步获得了PCA分析结果,并观察到明显的组间差异。但如果想把结果往文章中摆放,上图肯定是不行的,起码要让它好看一些。因此接下来,继续展示如何绘制一个好看的PCA图。
例如这里选择使用ggplot2包美化PCA图,它是一款非常出名的R语言作图包。不过在使用ggplot2作图之前,需要事先在上述PCA分析结果中将关键信息提取出,例如样本点在PCA图中的位置信息,以及PCA轴的贡献度等。
#提取样本在 PCA 前两轴中的坐标
pca_sample <- data.frame(gene.pca$ind$coord[ ,1:2])
head(pca_sample)
#提取 PCA 前两轴的贡献度
pca_eig1 <- round(gene.pca$eig[1,2], 2)
pca_eig2 <- round(gene.pca$eig[2,2],2 )
随后,加载ggplot2作图包,根据提取出的样本位置坐标以及PCA轴的贡献度数值,绘制二维散点图表示PCA结果。在同时,我们也将样本分组文件读取到R中用于指定样本的分组信息,以在图中使用不同的颜色表示不同组的样本。
FactoMineR包也能用于绘制这类统计图,以上述添加层次聚类的PCA继续。
#读取并合并样本分组信息
group <- read.delim('group.txt', row.names = 1, sep = '\t', check.names = FALSE)
group <- group[rownames(pca_sample), ]
pca_sample <- cbind(pca_sample, group)
pca_sample$samples <- rownames(pca_sample)
head(pca_sample) #作图数据中包含了样本坐标和分组信息
#ggplot2 绘制二维散点图
library(ggplot2)
p <- ggplot(data = pca_sample, aes(x = Dim.1, y = Dim.2)) +
geom_point(aes(color = group), size = 3) + #根据样本坐标绘制二维散点图
scale_color_manual(values = c('orange', 'purple')) + #自定义颜色
theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'),
legend.key = element_rect(fill = 'transparent')) + #去除背景和网格线
labs(x = paste('PCA1:', pca_eig1, '%'), y = paste('PCA2:', pca_eig2, '%'), color = '') #将 PCA 轴贡献度添加到坐标轴标题中
p
#标识样本名称,使用 ggplot2 的拓展包 ggrepel 来完成
library(ggrepel)
p <- p +
geom_text_repel(aes(label = samples), size = 3, show.legend = FALSE,
box.padding = unit(0.5, 'lines'))
p
样式是不是比最初的好看很多?
再一次,能够很清晰地从图中观察到,处理组和对照组的基因表达值整体差异是非常明显的,因为两组的样本能够在PCA图中区分很开。
4 可选添加样本聚类
继续,可以选择在PCA图中展示“样本聚类”。方法大致分为两种,一种是通过样本点的坐标拟合置信椭圆,另一种是直接将各组的边界区样本点以多边形连接。不过需要注意的是,这种方法并不是真正的聚类,而是一种用于在作图时更好地区分不同组的方法。
#添加 95% 置信椭圆,可用于表示对象分类,但只能适用于各组样本数大于 5 个的情况
p + stat_ellipse(aes(color = group), level = 0.95, show.legend = FALSE)
p + stat_ellipse(aes(fill = group), geom = 'polygon', level = 0.95, alpha = 0.1, show.legend = FALSE) +
scale_fill_manual(values = c('orange', 'purple'))
#多边形连接同类别对象边界的样式,适用于各组样本数大于 3 个的情况
library(plyr)
cluster_border <- ddply(pca_sample, 'group', function(df) df[chull(df[[1]], df[[2]]), ])
p + geom_polygon(data = cluster_border, aes(color = group), fill = NA, show.legend = FALSE)
p + geom_polygon(data = cluster_border, aes(fill = group), alpha = 0.2, show.legend = FALSE) +
scale_fill_manual(values = c('orange', 'purple'))
这样,一个完整的PCA分析过程就完整地展示出来了,包括输入文件准备,如何计算PCA,以及PCA图的可视化等,还是非常简单的对吗?