- 鉴于大量的转录组数据,可能出现的一个问题是“如果A组和B组都进行了转录组研究并报告了一些结果,这些结果的相容性如何?”目前基于转录组或芯片数据进行meta-analysis的方法很多,我们可以在数据库中寻找大量类似的实验结果用于meta-analysis,而WGCNA可以在转录组/芯片数据中构建无标度网络并将基因的表达水平与样本表型关联起来,这在转录组分析中发挥了十分重要的作用,在这里我们可以使用WGCNA将两组/两组以上的数据联合起来,用于阐述不同实验结果/不同物种间的基因表达模式的关联
- Miller JA, Horvath S, Geschwind DH. (2010) Divergence of human and mouse brain transcriptome highlights Alzheimer disease pathways. Proc Natl Acad Sci U S A. 2010 Jul 13;107(28):12698-703. 以下分析是基于该文章的精简版
#首先安装一些依赖包,这里有一些包年代久远可能会报错
install.packages(c("impute","dynamicTreeCut","qvalue","flashClust","Hmisc","WGCNA"))
随后下载示例数据,该数据包括4组样本,分别是:
- datExprA1 and datExprA2 – two data sets from the Illumina human ref-12 platform
- datExprB1 and datExprB2 – data sets from the Illumina human ref-12 and Affymetrix HG-U133A platforms, respectively (datExprA1 and datExprB1 are the same).
- probesI/A – probe set IDs for human ref-12 and HG-U133A platforms
- genesI/A – gene symbols corresponding to probesI/A
数据预处理
首先筛选探针,进行gene_symbol的注释以及初筛等操作
load("/path/metaAnalysisData.RData")
library(WGCNA)
datExprB1g = (collapseRows(datExprB1,genesI,probesI))[[1]]
datExprB2g = (collapseRows(datExprB2,genesA,probesA))[[1]]
#您需要将分析限制在两个数据集中都表达的基因/探针上。
commonProbesA = intersect (rownames(datExprA1),rownames(datExprA2))
datExprA1p = datExprA1[commonProbesA,]
datExprA2p = datExprA2[commonProbesA,]
commonGenesB = intersect (rownames(datExprB1g),rownames(datExprB2g))
datExprB1g = datExprB1g[commonGenesB,]
datExprB2g = datExprB2g[commonGenesB,]
接下来我们需要评估数据集间的关联,以判断这些数据可否进行联合分析,首先分别计算每个数据的的相容性如何?”目前基于转录组或芯片数据进行meta-analysis的方法很多,我们可以在数据库中寻找大量类似的实验结果用于meta-analysis,而WGCNA可以在转录组/芯片数据中构建无标度网络并将基因的表达水平与样本表型关联起来,这在转录组分析中发挥了十分重要的作用,在这里我们可以使用WGCNA将两组/两组以上的数据联合起来,用于阐述不同实验结果/不同物种间的基因表达模式的关联
- Miller JA, Horvath S, Geschwind DH. (2010) Divergence of human and mouse brain transcriptome highlights Alzheimer disease pathways. Proc Natl Acad Sci U S A. 2010 Jul 13;107(28):12698-703. 以下分析是基于该文章的精简版
#首先安装一些依赖包,这里有一些包年代久远可能会报错
install.packages(c("impute","dynamicTreeCut","qvalue","flashClust","Hmisc","WGCNA"))
数据预处理
首先筛选探针,进行gene_symbol的注释以及初筛等操作
load("/path/metaAnalysisData.RData")
library(WGCNA)
library(flashClust)
datExprB1g = (collapseRows(datExprB1,genesI,probesI))[[1]]
datExprB2g = (collapseRows(datExprB2,genesA,probesA))[[1]]
#您需要将分析限制在两个数据集中都表达的基因/探针上。
commonProbesA = intersect (rownames(datExprA1),rownames(datExprA2))
datExprA1p = datExprA1[commonProbesA,]
datExprA2p = datExprA2[commonProbesA,]
commonGenesB = intersect (rownames(datExprB1g),rownames(datExprB2g))
datExprB1g = datExprB1g[commonGenesB,]
datExprB2g = datExprB2g[commonGenesB,]
接下来我们需要评估数据集间的关联,以判断这些数据可否进行联合分析,首先分别计算每个节点的加权网络连接度,随后绘制相关性散点图查看相关性与P值判断数据是否可以联合分析,B组数据由于来自不同的平台,数据间的相关性比较低,但是P值很显著(P = 2.9e-84)我们也可以将其用于后续的分析
softPower = 10
rankExprA1= rank(rowMeans(datExprA1p))
rankExprA2= rank(rowMeans(datExprA2p))
random5000= sample(commonProbesA,5000)
rankConnA1= rank(softConnectivity(t(datExprA1p[random5000,]),type="signed",power=softPower))
rankConnA2= rank(softConnectivity(t(datExprA2p[random5000,]),type="signed",power=softPower))
rankExprB1= rank(rowMeans(datExprB1g))
rankExprB2= rank(rowMeans(datExprB2g))
random5000= sample(commonGenesB,5000)
rankConnB1= rank(softConnectivity(t(datExprB1g[random5000,]),type="signed",power=softPower))
rankConnB2= rank(softConnectivity(t(datExprB2g[random5000,]),type="signed",power=softPower))
par(mfrow=c(2,2))
verboseScatterplot(rankExprA1,rankExprA2, xlab="Ranked Expression (A1)",
ylab="Ranked Expression (A2)")
verboseScatterplot(rankConnA1,rankConnA2, xlab="Ranked Connectivity (A1)",
ylab="Ranked Connectivity (A2)")
verboseScatterplot(rankExprB1,rankExprB2, xlab="Ranked Expression (B1)",
ylab="Ranked Expression (B2)")
verboseScatterplot(rankConnB1,rankConnB2, xlab="Ranked Connectivity (B1)",
ylab="Ranked Connectivity (B2)")
构建共表达网络
出于计算的原因和简单性,我们首先选择数据集A1中表达量最高的5000个探针(通常不会这样做),然后每个基因只保留1个探针(如上所述),总共保留4746个基因。
keepGenesExpr = rank(-rowMeans(datExprA1p))<=5000
datExprA1g = datExprA1p[keepGenesExpr,]
datExprA2g = datExprA2p[keepGenesExpr,]
keepGenesDups = (collapseRows(datExprA1g,genesI,probesI))[[2]]
datExprA1g = datExprA1g[keepGenesDups[,2],]
datExprA2g = datExprA2g[keepGenesDups[,2],]
rownames(datExprA1g)<-rownames(datExprA2g)<-keepGenesDups[,1]
随后计算连接度并构建TOM矩阵
adjacencyA1 = adjacency(t(datExprA1g),power=softPower,type="signed");
diag(adjacencyA1)=0
dissTOMA1 = 1-TOMsimilarity(adjacencyA1, TOMType="signed")
geneTreeA1 = flashClust(as.dist(dissTOMA1), method="average")
adjacencyA2 = adjacency(t(datExprA2g),power=softPower,type="signed");
diag(adjacencyA2)=0
dissTOMA2 = 1-TOMsimilarity(adjacencyA2, TOMType="signed")
geneTreeA2 = flashClust(as.dist(dissTOMA2), method="average")
#绘制基因层次聚类树
par(mfrow=c(1,2))
plot(geneTreeA1,xlab="",sub="",main="Gene clustering on TOM-based dissimilarity (A1)",
labels=FALSE,hang=0.04);
plot(geneTreeA2,xlab="",sub="",main="Gene clustering on TOM-based dissimilarity (A2)",
labels=FALSE,hang=0.04);
接下来,我们将根据数据集A1确定模块(在实际情况下,我们通常会构建对照数据集的模块作为参照)。我们使用此代码自动显示四个不同的模块拆分,可以从中进行选择。
mColorh=NULL
for (ds in 0:3){
tree = cutreeHybrid(dendro = geneTreeA1, pamStage=FALSE,
minClusterSize = (30-3*ds), cutHeight = 0.99,
deepSplit = ds, distM = dissTOMA1)
mColorh=cbind(mColorh,labels2colors(tree$labels));
}
#pdf("Module_choices.pdf", height=10,width=25);
plotDendroAndColors(geneTreeA1, mColorh, paste("dpSplt =",0:3), main = "",dendroLabels=FALSE);
#dev.off()
modulesA1 = mColorh[,1] # (Chosen based on plot below)
#详细过程我们需要参照cutreeHybrid这个函数,我们提供了4个整数。使用四个等级的群集拆分敏感度的粗略控制。值越高,将产生越来越多的小簇。
在这里选择使用deepsplit=0(顶行),这样就会有少量的大模块。根据分析的目的,有时最好选择更多的小模块。在这种情况下,将选择1-3的深度分割值。
接下来,我们计算每个模块的主成分。第一个PC被称为模块的特征基因(module eigengene [ME]),表示模块中所有基因的最大方差百分比。换句话说,如果我们展示模块X的ME做某事,那么模块X中的大多数基因也很有可能做同样的事情。
PCs1A = moduleEigengenes(t(datExprA1g), colors=modulesA1)
ME_1A = PCs1A$eigengenes
distPC1A = 1-abs(cor(ME_1A,use="p"))
distPC1A = ifelse(is.na(distPC1A), 0, distPC1A)
pcTree1A = hclust(as.dist(distPC1A),method="a")
MDS_1A = cmdscale(as.dist(distPC1A),2)
colorsA1 = names(table(modulesA1))
#绘图展示模块之间关联程度
plot(pcTree1A, xlab="",ylab="",main="",sub="")
plot(MDS_1A, col= colorsA1, main="MDS plot", cex=2, pch=19)
ordergenes = geneTreeA1$order
plot.mat(scale(log(datExprA1g[ordergenes,])) , rlabels= modulesA1[ordergenes], clabels=
colnames(datExprA1g), rcols=modulesA1[ordergenes])
for (which.module in names(table(modulesA1))){
ME = ME_1A[, paste("ME",which.module, sep="")]
barplot(ME, col=which.module, main="", cex.main=2,
ylab="eigengene expression",xlab="array sample")
};
#现在我们已经有了所有的WGCNA变量和模块定义,我们可以开始评估网络A1中#的模块在网络A2中的情况。作为定性评估,我们将A1中的模块强加给数据集A2
#的网络,然后绘制出结果网络。
plotDendroAndColors(geneTreeA1, modulesA1, "Modules", dendroLabels=FALSE, hang=0.03, addGuide=TRUE,
guideHang=0.05, main="Gene dendrogram and module colors (A1)")
plotDendroAndColors(geneTreeA2, modulesA1, "Modules", dendroLabels=FALSE, hang=0.03, addGuide=TRUE,
guideHang=0.05, main="Gene dendrogram and module colors (A2)")
我们可以从这些模块标签在A2的情况发现,它们具有非常好的保存性。需要注意的是,在第二个数据集中通常不可能看到明显的模型标签分组,即使存在显著的数据关联以及模块保留能力。
为了量化这个结果,我们利用WGCNA库中内置的另一个函数:
modulePreservation
。此函数使用多种策略评估一项研究中的模块在另一项研究中的保存情况,并输出一个Z分数摘要。一般来说,
Zsummary.pres
的值越高,模块在数据集之间的保存程度越高:510表示高度保存。灰色模块包含未聚类的基因,而金色模块包含随机基因。一般来说,这些模块的Z分数应该比大多数其他模块低。在这种情况下,我们发现所有模块都保存得很好。
multiExpr = list(A1=list(data=t(datExprA1g)),A2=list(data=t(datExprA2g)))
multiColor = list(A1 = modulesA1)
mp=modulePreservation(multiExpr,multiColor,referenceNetworks=1,verbose=3,networkType="signed",
nPermutations=30,maxGoldModuleSize=100,maxModuleSize=400)
stats = mp$preservation$Z$ref.A1$inColumnsAlsoPresentIn.A2
stats[order(-stats[,2]),c(1:2)]
计算模块中的基因与ME的关联程度
Module membership (kME) 是一个有用的值,因为它可以用来测量每个基因和每个ME之间的相关性,因此即使是最初没有分配到模块的基因也可以包含在网络间的比较中。
geneModuleMembership1 = signedKME(t(datExprA1g), ME_1A)
colnames(geneModuleMembership1)=paste("PC",colorsA1,".cor",sep="");
MMPvalue1=corPvalueStudent(as.matrix(geneModuleMembership1),dim(datExprA1g)[[2]]);
colnames(MMPvalue1)=paste("PC",colorsA1,".pval",sep="");
Gene = rownames(datExprA1g)
kMEtable1 = cbind(Gene,Gene,modulesA1)
for (i in 1:length(colorsA1))
kMEtable1 = cbind(kMEtable1, geneModuleMembership1[,i], MMPvalue1[,i])
colnames(kMEtable1)=c("PSID","Gene","Module",sort(c(colnames(geneModuleMembership1),
colnames(MMPvalue1))))
#现在对A2重复上述步骤,使用来自A1的模块赋值来确定A2中的kME值。
# First calculate MEs for A2, since we haven't done that yet
PCs2A = moduleEigengenes(t(datExprA2g), colors=modulesA1)
ME_2A = PCs2A$eigengenes
geneModuleMembership2 = signedKME(t(datExprA2g), ME_2A)
colnames(geneModuleMembership1)=paste("PC",colorsA1,".cor",sep="");
MMPvalue2=corPvalueStudent(as.matrix(geneModuleMembership2),dim(datExprA2g)[[2]]);
colnames(MMPvalue2)=paste("PC",colorsA1,".pval",sep="");
kMEtable2 = cbind(Gene,Gene,modulesA1)
for (i in 1:length(colorsA1))
kMEtable2 = cbind(kMEtable2, geneModuleMembership2[,i], MMPvalue2[,i])
colnames(kMEtable2)=colnames(kMEtable1)
- 我们首先要做的是将A1中每个基因的kME值与A2中每个基因相应的kME值进行比较。具有高相关性的点的模块被高度保留。下面是所有基因(左)和被分配进该模块的基因子集(右)创建这些图的示例图像。
- 我们可以做的第二件事是通过确定哪些基因在两个网络中都具有极高的kME值来确定哪些基因是两个网络中的枢纽。
#pdf("all_kMEtable2_vs_kMEtable1.pdf",height=8,width=8)
for (c in 1:length(colorsA1)){
verboseScatterplot(geneModuleMembership2[,c],geneModuleMembership1[,c],main=colorsA1[c],
xlab="kME in A2",ylab="kME in A1")
};
#pdf("inModule_kMEtable2_vs_kMEtable1.pdf",height=8,width=8)
for (c in 1:length(colorsA1)){
inMod = modulesA1== colorsA1[c]
verboseScatterplot(geneModuleMembership2[inMod,c],geneModuleMembership1[inMod,c],main=colorsA1[c],
xlab="kME in A2",ylab="kME in A1")
};
topGenesKME = NULL
for (c in 1:length(colorsA1)){
kMErank1 = rank(-geneModuleMembership1[,c])
kMErank2 = rank(-geneModuleMembership2[,c])
maxKMErank = rank(apply(cbind(kMErank1,kMErank2+.00001),1,max))
topGenesKME = cbind(topGenesKME,Gene[maxKMErank<=10])
};
colnames(topGenesKME) = colorsA1
这两种类型的散点图传达了相似但不完全相同的信息。使用所有基因(左)可以包含所有正相关和负相关的基因,但通常也包含很多噪声(尽管在本例中没有)。只使用模块内基因(右)是评估hub基因在不同数据集间的保守程度:如果这些基因显示出集合间的相关性,那么位于图右上角的基因很可能是数据集之间的公共hub基因。(Hub基因是与MEs和模块内高连通性有显著相关性的基因)
注释模块以及后续分析
为了可视化生成的网络模块,我们可以从网络输出数据导入VisANT
,VisANT
是一个独立的可视化java程序,可在http://VisANT.bu.edu/
上获得。VisANT可以让你直观地看到一个模块中的中心基因,是大多数人用来制作模块图片的程序。关于如何使用VisANT的教程可以在网站上找到。我们可以使用作者封装的代码提取模块中的基因用于VisANT的输入文件
source("tutorialFunctions.R")
for (co in colorsA1[colorsA1!="grey"])
visantPrepOverall(modulesA1, co, t(datExprA1g), rownames(datExprA1g), 500, softPower, TRUE)
for (co in colorsA1[colorsA1!="grey"])
visantPrepOverall(modulesA1, co, t(datExprA2g), rownames(datExprA2g), 500, softPower, TRUE)
这个函数会将很多文件输出到当前目录中,每个模块都有两个文件:
1)_connectivityOverall.csv:此文件包含给定模块中从最高到最低模块内连接(kin)排序的所有基因及其平均表达的列表。所以排在第一位的基因是中枢基因。
2)_visantOverall.csv:此文件包含VisANT所需的所有输入。注意,只有前五列应该复制到VisANT中。前两列表示模块中拓扑重叠度最高的基因(第5列)。第3列必须是“0”,第4列是要绘制的线的颜色(“M1002”是橙色) 通过该软件我们可以查看不同数据之间不同的表达模式,该示例中我们可以很清楚的发现SCAMP5是A1特异表达的,我们可以选择这样的基因进行后续的分析