WGCNA原理和分析流程

WGCNA全称weighted gene co-expression network analysis,即加权基因共表达网络分析。它是一种分析多个样本基因表达模式的分析方法,可将表达模式相似的基因进行聚类,并分析模块与特定性状或表型之间的关联关系,在研究表型性状与基因关联分析等方面的研究中被广泛应用。
关于WGCNA最简单的解释就是样本之间的各个基因是否存在共同表达的模式。例如基因A和基因B是否在某一个阶段中存在相同的表达模式——两者同时上调表达,还是同时下调表达。这个方法就是利用这样思路将样本中基因表达进行分析,探究基因间是否具有共表达的现象,并且根据一定的数值给某一团共表达的基因划分成一个模块,这样聚在一起的不同的团的基因就划分为不同的模块。例如关于调控花青素合成的基因可能就会聚类在同一个模块里面,关于调控叶绿素合成则可能会聚类在另一个模块里面。但是,WGCNA的分析还不止于此,它还可以利用这些模块和表型数据进行聚类,找到这个模块中的核心基因(权重较高的一些基因),也就是hubgene。

WGCNA分析流程主要有以下几步:

  • 数据输入与清洗(筛选)
  • 网络构建与模块检测(有三种方法可以实现)
  • 模块与表型数据关联并识别重要基因
  • 网络交互分析(GO注释等)
  • WGCNA网络可视化
  • 导出网络互作数据(Cytoscape)
核心概念:
  • 无标度网络(scale free):真实的生物学网络大多属于无标度网络,服从pow law分布,即幂律分布 p(k)~ k−γ。(随机网络一般服从泊松Poisson分布)
    在无标度网络中存在一个显著的特点就是网络中存在少数度很高的节点(远超平均度),这样的节点称为'Hub'。通常认为这样的节点在网络中具有重要作用,在这样的节点周围存在保守的网络结构。
    无标度网络节点的度分布特征使得它有一个很大的特点,那就是稳健性:随机去除网络中的一个节点,网络还能依然保持(绝大多数节点的度很低)。但是它也有脆弱的一面:那就是去除网络中的hub节点,网络就散了。但是hub节点只是网络中极少数的几个节点,被攻击的概率非常小。
  • 共表达网络:定义为加权基因网络点代表基因边代表基因之前是否发生显著共表达。加权是指对相关性值进行冥次运算 (冥次的值也就是软阈值 (power, pickSoftThreshold这个函数所做的就是确定合适的power))。
    在得到两个基因的相关系数值之后,如何决定这两个基因在构建网络时是否连边?如果定义一个阈值,比如有统计学意义的r>0.9,那么就连边;否则,就不连边。这个办法就是hard threshold(也即不加权unweighted)。这个办法有以下缺点:1:如何确定这个阈值?由于这个阈值主观性较强,有人觉得0.9就是强相关,也有人会认为0.8也是强相关。2:对于真实的生物学网络,这种二元定义连边的方法是否真的适合?
    相对于硬阈值来说,使用软阈值强化了强相关,弱化了弱相关或负相关,使得相关性数值更符合无标度网络特征,更具有生物意义。如果没有合适的power,一般是由于部分样品与其它样品因为某种原因差别太大导致的,可根据具体问题移除部分样品或查看后面的经验值。
  • Module(模块):高度相关 (具有高度连接性) 的一组基因,行使相同或相似的功能。在无向网络中,模块内是高度相关的基因。在有向网络中,模块内是高度正相关的基因。把基因聚类成模块后,可以对每个模块进行三个层次的分析:1. 功能富集分析查看其功能特征是否与研究目的相符;2. 模块与性状进行关联分析,找出与关注性状相关度最高的模块;3. 模块与样本进行关联分析,找到样品特异高表达的模块。

  • Connectivity (连接度):类似于网络中 “度” (degree)的概念。每个基因的连接度是与其相连的基因的边属性之和(可以理解为某个基因与它周围基因发生了多少交流的量化)。

  • Intramodular connectivity:给定基因与给定模型内其他基因的关联度,判断基因所属关系。

  • Hub gene:关键基因 (连接度最多或连接多个模块的基因)。

  • Module eigengene E:给定模型的第一主成分,代表整个模型的基因表达谱。这个是个很巧妙的梳理,和PCA类似,很好的用一个向量代替了一个矩阵,方便后期计算。(降维除了PCA,还可以看看tSNE)

  • Eigengene significance:指模块的eigengene与外部的样本性状的相关性

  • Module Membership (MM):给定基因表达谱与给定模型的eigengene的相关性。其实就是所有基因表达谱与这个模块的eigengene的相关性(cor)。是一个具有所有用来做WGCNA分析基因数长度的向量,每一个值代表这个基因与模块之间的关系。如果这个值的绝对值接近0,那么这个基因就不是这个模块中的一部分,如果这个值的绝对值接近1,那么这个基因就与这个模块高度相关。
    一般,每个模块中的基因都会与被分配到的模块高度相关,表明了模块内部高度的连接性。(这个值与后面hub基因的选择相关)

  • Gene Significance (GS):基因和表型性状比如体重之间的相关性的绝对值。总的来说,就是为了将表型特征信息与共表达网络联合起来,比如体重与哪个模块高度相关。
    详细一点专业一点就是:每一个基因的表达值与表型性状之间的相关性的绝对值。0表示这个基因与这个性状不相关,1表示高度相关。如果一个模块中的基因都有这个性状高度相关,那么这个模块也就与这个性状高度相关。

  • Module Significance:模块内所有基因的GS平均值。值越大,模块与表型的相关性越高。

  • Adjacency matrix (邻接矩阵):基因和基因之间的加权相关性值构成的矩阵。

  • TOM (Topological overlap matrix):把邻接矩阵转换为拓扑重叠矩阵,以降低噪音和假相关,获得的新距离矩阵,这个信息可拿来构建网络或绘制TOM图。

1. 数据输入、清洗和预处理

输入数据 (2个矩阵) 和参数选择:

  • WGCNA本质是基于相关系数的网络分析方法,适用于多样品数据模式,一般要求样本数多于15个。样本数多于20时效果更好,样本越多,结果越稳定。
  • 基因表达矩阵:常规表达矩阵即可,即基因在行,样品在列,进入分析前做一个转置。RPKM、FPKM或其它标准化方法影响不大,推荐使用Deseq2的varianceStabilizingTransformation或log2(x+1)对标准化后的数据做个转换。如果数据来自不同的批次,需要先移除批次效应。如果数据存在系统偏移,需要做下quantile normalization。
  • 性状矩阵:用于关联分析的性状必须是数值型特征。如果是区域或分类变量,需要转换为0-1矩阵的形式(1表示属于此组或有此属性,0表示不属于此组或无此属性,如样品分组信息WT, KO, OE)。
1.1 载入数据
#设定工作路径
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
femData = read.csv("LiverFemale3600.csv") #载入基因表达量数据
##这份*.csv文件是示例中的的3600个基因的表达数据
dim(femData)
names(femData)
#行为基因,列为不同样本的基因表达量或其他信息

提取出表达量的数据 ,删去不需要的数据重新生成矩阵

datExpr0 = as.data.frame(t(femData[, -c(1:8)]))  #提取加转置
names(datExpr0) = femData$substanceBXH #基因名字
rownames(datExpr0) = names(femData)[-c(1:8)]  #样品名字
dim(datExpr0)
# [1]  135 3600

得到的datExpr0 就是一个以每行为样本,一列为一个基因的数据框,包含3600个基因和135个样本

1.2 检查缺失值和识别离群值(异常值)
gsg = goodSamplesGenes(datExpr0, verbose = 3);
gsg$allOK

goodSamplesGenes()函数可以识别缺失值,权重低于阈值的基因和zero-variance基因。
如果gsg$allOK的结果为TRUE,证明没有缺失值,可以直接下一步。如果为FALSE,则需要用以下函数进行删除缺失值。

if (!gsg$allOK)
{
  # Optionally, print the gene and sample names that were removed:
  if (sum(!gsg$goodGenes)>0)
    printFlush(paste("Removing genes:", paste(names(datExpr0)[!gsg$goodGenes], collapse = ", ")));
  if (sum(!gsg$goodSamples)>0)
    printFlush(paste("Removing samples:", paste(rownames(datExpr0)[!gsg$goodSamples], collapse = ", ")));
  # Remove the offending genes and samples from the data:
  datExpr0 = datExpr0[gsg$goodSamples, gsg$goodGenes]
}

注:在这一步之后,一般会有一个筛选基因的过程。因为电脑的配置问题,一般来说运行几万个基因的表达量来构建TOM矩阵和邻接矩阵是非常吃力的,我试过把全部的基因都用来构建网络,但是构建矩阵的过程非常费时间,而且很难能运行成功。所以在完成剔除异常值之后,我们还需要进一步挑选基因。至于怎么筛选基因要看自己的目的,粗暴一点的可以按表达量为前5000的进行提取,通常用5000个基因进行分析。

聚类所有样本,观察是否有离群值或异常值。

sampleTree = hclust(dist(datExpr0), method = "average")
sizeGrWindow(12,9) #视图
par(cex = 0.6);
par(mar = c(0,4,2,0))
plot(sampleTree, main = "Sample clustering to detect outliers", sub="", xlab="", cex.lab = 1.5,
     cex.axis = 1.5, cex.main = 2)

如果有离群值,则要删去离群的样本,如果没有跳到下一步。

# 删除离群样本
abline(h = 15, col = "red") #划定需要剪切的枝长
clust = cutreeStatic(sampleTree, cutHeight = 15, minSize = 10)
# 这时候会从高度为15这里横切,把离群样本分开
table(clust)   
# clust
#   0   1 
#   1 134 
keepSamples = (clust==1)  #保留非离群(clust==1)的样本
datExpr = datExpr0[keepSamples, ]  #去除离群值后的数据
nGenes = ncol(datExpr)
nSamples = nrow(datExpr)

这个数据中删除了1个离群样本,得到的datExpr就是134样本*3600基因的矩阵

1.3 载入表型数据
traitData = read.csv("ClinicalTraits.csv");
dim(traitData)  #每行是一个样本,每列是一种信息
names(traitData)
#删除我们不需要的数据
allTraits = traitData[, -c(31, 16)];
allTraits = allTraits[, c(2, 11:36) ];  #只保留数值型数据
dim(allTraits)
names(allTraits)

因为表型数据和基因表达量数据中并不是全部信息都能匹配上,例如表型数据中的样本可能在基因表达量数据中不存在,这时候需要将两者进行匹配,找共有的数据才能分析。

将临床表征数据和表达数据进行匹配(用样本名字进行匹配)
femaleSamples = rownames(datExpr);
traitRows = match(femaleSamples, allTraits$Mice);
datTraits = allTraits[traitRows, -1];
rownames(datTraits) = allTraits[traitRows, 1];
collectGarbage()

得到的datTraits就是134个样本,26个特征的矩阵。

可视化表型数据与基因表达量数据的联系,重构样本聚类树

sampleTree2 = hclust(dist(datExpr), method = "average")
traitColors = numbers2colors(datTraits, signed = FALSE) #用颜色代表关联度
plotDendroAndColors(sampleTree2, traitColors,
                    groupLabels = names(datTraits),
                    main = "Sample dendrogram and trait heatmap")
颜色越深,代表这个表型数据与这个样本的基因表达量关系越密切,灰色是缺失值

图片结果解释了临床数据和基因表达量的关联程度,保存数据。

save(datExpr, datTraits, file = "FemaleLiver-01-dataInput.RData")

2. 构建表达网络

构建表达网络是WGCNA分析中最为关键的一步,是否构建成功、是否构建正确对后期模块的划分和关联表型数据筛选核心基因至关重要。
挑选软阈值是构建网络拓扑分析的关键,选择软阈值是基于近无尺度拓扑标准的。很多人会因为无法挑选合适的软阈值而卡在了这一步,不能往下走。其次就是构建TOM矩阵或者邻接矩阵的时候运行大数据无法成功。

除此之外,构建表达网络后划分模块的方法有三种,分别是一步法逐步法分步法,不同的方法各有优缺点,要根据自己的需求选择。这三种方法的主要区别是:
> 一步法:适合处理较少的数据量,方便快捷,自动化程度高(该教程)
> 逐步法:适合处理适中的数据量,可以自定义参数
> 分步法:适合处理较大的数据量(5000个以上基因),需要分不同的block划分模块,自定义参数

下面先逐步说一下构建表达网络的步骤。

2.0 参数设置
#与第一步设置一样
# 设定工作路径
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
# 载入第一步保存的数据
lnames = load(file = "FemaleLiver-01-dataInput.RData");
lnames
2.1 构建自动化网络和检测模块

选择软阈值(pickSoftThreshold()函数所做的就是确定合适的power,也就是冥次的值/软阈值。软阈值的筛选原则是使构建的网络更符合无标度网络特征)

powers = c(c(1:10), seq(from = 12, to=20, by=2))
sft = pickSoftThreshold(datExpr, powerVector = powers, verbose = 5)

得到的sft是一个list,保存了最佳软阈值和构建的scalefree网络的一些参数fitIndices

这几列依次是power值、R方、斜率、truncated R方、网络平均连接度、中位连接度、最大连接度
#绘图准备
sizeGrWindow(9, 5)
par(mfrow = c(1,2))
cex1 = 0.9 #字符大小
  • 无标度拓扑拟合指数
plot(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
     xlab="Soft Threshold (power)",ylab="Scale Free Topology Model Fit,signed R^2",type="n",
     main = paste("Scale independence"));
text(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
     labels=powers,cex=cex1,col="red");
     abline(h=0.90,col="red")  #查看位于0.9以上的点,官网是0.85

一般来说,无标度拓扑拟合指数这个图是用来选择软阈值的一个根据。例如下图是1到20(有些教程会写到1到30)。我们一般选择在0.9以上的,第一个达到0.9以上数值。下图的6是第一个达到0.9的数值,可以考虑6作为软阈值。
如果在0.9以上就没有数值了,我们就要降低标准,但是最低不能小于0.8。

横轴是Soft threshold (power),纵轴是无标度网络的评估参数,数值越高,网络越符合无标度特征 (non-scale)
  • 平均连接度
plot(sft$fitIndices[,1], sft$fitIndices[,5],
     xlab="Soft Threshold (power)",ylab="Mean Connectivity", type="n",
     main = paste("Mean connectivity"))
text(sft$fitIndices[,1], sft$fitIndices[,5], labels=powers, cex=cex1,col="red")

从下图可以看出,数值为6的时候,已经开始持平,则软阈值为6时,网络的连通性好。

  • 运行下面的代码,如果有合适的软阈值,系统会自动推荐。
sft$powerEstimate
# [1] 6
# 如果显示的结果为 NA,则表明系统无法给出合适的软阈值,这时候就需要自己挑选软阈值。
# 手动挑选软阈值的大致规则如上面所述。

⚠️无向网络在power小于15或有向网络power小于30内,没有一个power值可以使无标度网络图谱结构R2达到0.8或平均连接度降到100以下,可能是由于部分样品与其他样品差别太大造成的。这可能由批次效应样品异质性实验条件对表达影响太大等造成,可以通过绘制样品聚类查看分组信息、关联批次信息、处理信息和有无异常样品 (可以使用之前讲过的热图简化,增加行或列属性)。如果这确实是由有意义的生物变化引起的,也可以使用后面程序中的经验power值。

  • 经验power值 (无满足条件的power时选用)
if (is.na(power)){ 
  power = ifelse(nSamples<20, ifelse(type == "unsigned", 9, 18), 
                 ifelse(nSamples<30, ifelse(type == "unsigned", 8, 16), 
                        ifelse(nSamples<40, ifelse(type == "unsigned", 7, 14), 
                               ifelse(type == "unsigned", 6, 12))        
                 ) 
  ) 
}
2.2 一步法构建网络和模块检测

选好了power值就要开始构建网络了。

cor = WGCNA::cor #以免cor冲突报错
net = blockwiseModules(datExpr, power = 6,
                       TOMType = "unsigned", minModuleSize = 30,
                       reassignThreshold = 0, mergeCutHeight = 0.25,
                       numericLabels = TRUE, pamRespectsDendro = FALSE,
                       saveTOMs = TRUE,
                       saveTOMFileBase = "femaleMouseTOM",
                       verbose = 3)
cor = stats::cor #改回去
# power = 6是刚才选择的软阈值
#minModuleSize:模块中最少的基因数
#mergeCutHeight :模块合并阈值,阈值越大,模块越少(重要)
# corType: pearson or bicor
# numericLabels: 返回数字而不是颜色作为模块的名字,后面可以再转换为颜色
# saveTOMs = TRUE 最耗费时间的计算,存储起来,供后续使用
# saveTOMFileBase = "femaleMouseTOM"保存TOM矩阵,名字为"femaleMouseTOM"
#net$colors 包含模块分配,net$MEs 包含模块的模块特征基因。

这样net网络就构建好了

⚠️这个例子中blockwiseModules()保留了较多的默认参数,可以阅读帮助文档,调整网络结构和模块检测参数以使结果更符合生物学意义。

注意:maxBlockSize的参数默认的模块处理最大基因数为位5000,如果大于5000,这个函数会将数据集拆分为几块,这会破坏下面的一些绘图代码,即执行代码会导致错误。在分析更大数据集时需要执行以下操作之一:4GB运行内存可以处理8000~10000个,16GB最多可处理20000个,32GB最多可以处理30000个。如果要分析较大的数据集,需要用第三种构建网络的方法,即分模块,逐块分析。

# 查看划分的模块数和每个模块里面包含的基因个数
table(net$colors)
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# 99 609 460 409 316 312 221 211 157 123 106 100 94 91 77 76 58 47 34
# 以上结果表示一共可以分为18个模块 (不包括0),第二行是每个模块对应的基因数,有多到少。
# 从模块1开始,基因数逐渐减少。模块0是无法识别的基因数。

模块标识的层次聚类树状图,可以使用以下代码将树状图与颜色分配一起显示:

sizeGrWindow(12, 9)
mergedColors = labels2colors(net$colors)
plotDendroAndColors(net$dendrograms[[1]], mergedColors[net$blockGenes[[1]]],
                    "Module colors",
                    dendroLabels = FALSE, hang = 0.03,
                    addGuide = TRUE, guideHang = 0.05)
灰色的为未分类到模块的基因

如果需要修改树、模块成员、和模块合并标准,该包的recutBlockwiseTrees函数可以对结果进行修改,而无需重复计算网络和树状图。(推荐用第二种方法分步法实现)

保存分配模块和模块包含的基因信息。

moduleLabels = net$colors
moduleColors = labels2colors(net$colors)
MEs = net$MEs;
geneTree = net$dendrograms[[1]];
save(MEs, moduleLabels, moduleColors, geneTree,
     file = "FemaleLiver-02-networkConstruction-auto.RData")

MEs是134个样本*19个模块的矩阵(和PCA的PC类似)

3. 模块与表型数据关联并识别重要基因⚠️

3.0 参数设置与载入之前的分析结果
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
lnames = load(file = "FemaleLiver-01-dataInput.RData");
lnames
# [1] "datExpr"   "datTraits"
lnames = load(file = "FemaleLiver-02-networkConstruction-auto.RData")
lnames
# [1] "MEs"         
# [2] "moduleLabels"
# [3] "moduleColors"
# [4] "geneTree"  

这里使用的是一步法自动构建网络的分析结果,也可以用分步法、逐步法的分析结果。

3.1 模块-表型数据关联

在这个分析中,我们将识别与表型数据显著相关的模块。由于我们已经有每个模块的eigengene,只需要将eigengene与外部数据相关联,寻找重要的关联。

nGenes = ncol(datExpr);
nSamples = nrow(datExpr);
# 重新计算带有颜色标签的模块
MEs0 = moduleEigengenes(datExpr, moduleColors)$eigengenes
MEs = orderMEs(MEs0)
moduleTraitCor = cor(MEs, datTraits, use = "p"); #核心代码,计算了每个模块和每个基因的相关性
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples);
# 通过相关值对每个关联进行颜色编码
sizeGrWindow(10,6)
# 展示模块与表型数据的相关系数和 P值
textMatrix = paste(signif(moduleTraitCor, 2), "\n(",
                   signif(moduleTraitPvalue, 1), ")", sep = "");
dim(textMatrix) = dim(moduleTraitCor)
par(mar = c(6, 8.5, 3, 3));
# 用热图的形式展示相关系数
labeledHeatmap(Matrix = moduleTraitCor,
               xLabels = names(datTraits),
               yLabels = names(MEs),
               ySymbols = names(MEs),
               colorLabels = FALSE,
               colors = greenWhiteRed(50),
               textMatrix = textMatrix,
               setStdMargins = FALSE,
               cex.text = 0.5,
               zlim = c(-1,1),
               main = paste("Module-trait relationships"))
#colors = greenWhiteRed(50)不适用于红绿色盲患者,建议用 blueWhiteRed代替.
#该分析确定了几个重要的模块-特征关联。我们将体重作为感兴趣的特征来研究。

⚠️⚠️⚠️根据这个图选择感兴趣的模块

从图片可以看到颜色越红的模块表示与表型性状与该模块的基因高度正相关,而言是越绿表示高度负相关。可以看到棕色模块与体重的相关性非常高,所以下面会接着探讨这个模块中的基因与体重的关系。

3.2 基因与表型数据的关系(GS)和重要模块(MM):基因显著性和模块成员

我们将用基因的显著性GS定义为基因与性状的相关性(绝对值),以定量单个基因与我们感兴趣的性状(体重)的关联。对于每个模块,我们将用模块成员MM的定量测定定义为模块eigengene和基因表达特征的相关性。这样能够量化矩阵上所有基因和每个模块的相似性。

weight = as.data.frame(datTraits$weight_g);
names(weight) = "weight";
modNames = substring(names(MEs), 3)
geneModuleMembership = as.data.frame(cor(datExpr, MEs, use = "p"));
MMPvalue = as.data.frame(corPvalueStudent(as.matrix(geneModuleMembership), nSamples));
names(geneModuleMembership) = paste("MM", modNames, sep="");
names(MMPvalue) = paste("p.MM", modNames, sep="");
geneTraitSignificance = as.data.frame(cor(datExpr, weight, use = "p"));#和体重性状的关联
GSPvalue = as.data.frame(corPvalueStudent(as.matrix(geneTraitSignificance), nSamples));
names(geneTraitSignificance) = paste("GS.", names(weight), sep="");
names(GSPvalue) = paste("p.GS.", names(weight), sep="");
MMPvalue
GSPvalue
3.3 模块内分析:鉴定具有高GS和高MM的基因

使用GS和MM测量,可以识别与体重高度相关的基因,以及感兴趣的模块中的高度相关的成员。这个例子中,体重与棕色模块的关联度较高,因此我们在棕色模块中绘制基因显著性和模块成员关系的散点图。

# 运行以下代码可视化GS和MM
module = "brown"
column = match(module, modNames);
moduleGenes = moduleColors==module;
sizeGrWindow(7, 7);
par(mfrow = c(1,1));
verboseScatterplot(abs(geneModuleMembership[moduleGenes, column]),
                   abs(geneTraitSignificance[moduleGenes, 1]),
                   xlab = paste("Module Membership in", module, "module"),
                   ylab = "Gene significance for body weight",
                   main = paste("Module membership vs. gene significance\n"),
                   cex.main = 1.2, cex.lab = 1.2, cex.axis = 1.2, col = module)

⚠️⚠️⚠️根据这个图选择感兴趣的模块内感兴趣的基因

MM-GS图的每一个点:
图中的每一个点代表一个基因 (应该有3600个点),横坐标值表示基因与模块的相关性,纵坐标值表示基因与表型性状的相关性,这里可以看出与性状高度显著相关的基因往往是与这个性状显著相关的模块中的重要元素。

hubgene选取方法:
1. 上图右上角的基因可以作为hubgene
2. 根据连通度取top 10 (个数视情况而定)

3.4 输出网络分析结果

我们在找到了与我们感兴趣的表征高度相关的模块(在3.1中看到棕色模块与体重的相关性非常高),并通过MM测量确定了核心的参与者(核心基因hubgene),我们现在需要将这些数据合并起来,并输出为结果文件。

names(datExpr)#会返回所有在分析中的基因ID
names(datExpr)[moduleColors=="brown"]#返回属于棕色模块的基因ID
annot = read.csv(file = "GeneAnnotation.csv");
dim(annot)
names(annot)
probes = names(datExpr) # 匹配信息
probes2annot = match(probes, annot$substanceBXH);
sum(is.na(probes2annot)) # 检测是否有没有匹配上的ID号,正常来说为0,即全匹配上了。
#输出必要的信息:
geneInfo0 = data.frame(substanceBXH = probes,
                       geneSymbol = annot$gene_symbol[probes2annot],
                       LocusLinkID = annot$LocusLinkID[probes2annot],
                       moduleColor = moduleColors,
                       geneTraitSignificance,
                       GSPvalue);
 # 按照与体重的显著水平将模块进行排序:
 modOrder = order(-abs(cor(MEs, weight, use = "p")));
 #添加模块成员的信息:
 for (mod in 1:ncol(geneModuleMembership))
{
  oldNames = names(geneInfo0)
  geneInfo0 = data.frame(geneInfo0, geneModuleMembership[, modOrder[mod]],
                         MMPvalue[, modOrder[mod]]);
  names(geneInfo0) = c(oldNames, paste("MM.", modNames[modOrder[mod]], sep=""),
                       paste("p.MM.", modNames[modOrder[mod]], sep=""))
}
geneOrder = order(geneInfo0$moduleColor, -abs(geneInfo0$GS.weight));  # 排序
geneInfo = geneInfo0[geneOrder, ]
# 输出为CSV格式,可用fix(geneInfo)在R中查看:
write.csv(geneInfo, file = "geneInfo.csv")
所有模块计算出来的GS和MM值

后续就可以对这个表格进行操作。
比如选择brown模块的409个基因+将GS.weight按绝对值进行排序,挑选比较大的基因+筛选p.GS.weight有显著性的基因+比较高的MM.brwon值+p.MM.brwon有显著意义的=hub gene (和MM-GS图一个意思)

4. 网络交互分析(GO注释等)

这步其实是可选步骤,主要是将重要的基因进行功能注释,例如GO注释。

4.0 参数设置与载入数据
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
lnames = load(file = "FemaleLiver-01-dataInput.RData");
lnames
lnames = load(file = "FemaleLiver-02-networkConstruction-auto.RData")
lnames

我们之前分析了与体重weight高度相关的模块,为了有助于阐释在生物学上的意义,我们希望知道这些模块里的基因的基因本体,它们是否显著富集在某些功能类别中。

4.1 输出基因列表供在线软件服务使用

其中最简单的一种选择是导出基因识标符列表,该列表可以在几个常用的基因本体David和功能富集分析AmiGo中输入使用。例如,将brown棕色模块的LocusLinkID(entrez)标识符代码写到一个文件中:

annot = read.csv(file = "GeneAnnotation.csv");
probes = names(datExpr);
probes2annot = match(probes, annot$substanceBXH);
allLLIDs = annot$LocusLinkID[probes2annot];
intModules = c("brown", "red", "salmon")
for (module in intModules)
{
  # Select module probes
  modGenes = (moduleColors==module);
  # Get their entrez ID codes
  modLLIDs = allLLIDs[modGenes];
  # Write them into a file
  fileName = paste("LocusLinkIDs-", module, ".txt", sep="");
  write.table(as.data.frame(modLLIDs), file = fileName,
              row.names = FALSE, col.names = FALSE)
}
4.2 直接用R进行GO富集分析

WGCNA包包含了执行GO富集分析功能,但是要运行GO富集,需要安Biconductororg包的GO.db、AnnotationDBI和适当的生物体特定注释包。
注:
特定生物体的包以org.Xx.eg.db的形式命名。Xx代表生物体代码:Mm是小鼠、Hs是人类。酵母的注释包比较特别,用的是org.Sc.sgd.db。请访问 http://www.bioconductor.org 的 Bioconductor 主页下载并安装所需的软件包。
这个例子中研究的是小鼠的基因表达,所以要用到org.Mm.eg.db包。调用GO富集分析函数GOenrichmentAnalysis非常简单,该函数采用模块标签向量,以及给出标签的基因的Entrez(Locus Link)编码。

if (!require("BiocManager", quiet = TRUE))
  +     install.packages("BiocManager")
GOenr = GOenrichmentAnalysis(moduleColors, allLLIDs, organism = "mouse", nBestP = 10)
tab = GOenr$bestPTerms[[4]]$enrichment
以上结果是一个富集列表,包含每个模块颜色中10个最佳的条目。可以通过以下方式访问表中列的名称:
names(tab)
输出为*.CSV格式可用Excel打开
write.table(tab, file = "GOEnrichmentTable.csv", sep = ",", quote = TRUE, row.names = FALSE)
也可以直接删减一些内容,使其在R中快速显示出来:
keepCols = c(1, 2, 5, 6, 7, 12, 13);
screenTab = tab[, keepCols];
numCols = c(3, 4);
screenTab[, numCols] = signif(apply(screenTab[, numCols], 2, as.numeric), 2)  #将数字保留两位小数
将术语名称截断为最多 40 个字符:
screenTab[, 7] = substring(screenTab[, 7], 1, 40)
colnames(screenTab) = c("module", "size", "p-val", "Bonf", "nInTerm", "ont", "term name");
rownames(screenTab) = NULL;
options(width=95)
screenTab

5. 网络可视化 (TOM plot)

TOM矩阵是我们前面计算的相关性(邻接矩阵),通过命令转换之后得到拓扑重叠矩阵,以降低噪音和假相关。在转化成TOM矩阵。获得的新距离矩阵可以拿来构建网络或绘制TOM图。

5.0 参数设置
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
lnames = load(file = "FemaleLiver-01-dataInput.RData");
lnames
lnames = load(file = "FemaleLiver-02-networkConstruction-auto.RData")
lnames
nGenes = ncol(datExpr)
nSamples = nrow(datExpr)
5.1 可视化基因网络

可视化加权网络的方法之一是制作热图。热图的每行每列代表一个基因,浅色代表低邻接(重叠);深色代表高邻接(重叠)。以下代码是将一步法和逐步法的基础上绘制的热图,不适用于逐块分析法,如需要展示逐步法,需要修改代码将每块block进行可视化。

#计算TOM矩阵
dissTOM = 1-TOMsimilarityFromExpr(datExpr, power = 6);
plotTOM = dissTOM^7;
diag(plotTOM) = NA;
sizeGrWindow(9,9)
TOMplot(plotTOM, geneTree, moduleColors, main = "Network heatmap plot, all genes")

生成的热图可能需要大量的时间。可以限制基因的数量来加快绘图。但是基因子集的树状图看起来与所有基因的树状图不同,下面随机选取400个基因进行绘图:

nSelect = 400
set.seed(10);
select = sample(nGenes, size = nSelect);
selectTOM = dissTOM[select, select];
selectTree = hclust(as.dist(selectTOM), method = "average")
selectColors = moduleColors[select];
sizeGrWindow(9,9)
plotDiss = selectTOM^7;
diag(plotDiss) = NA;
TOMplot(plotDiss, selectTree, selectColors, main = "Network heatmap plot, selected genes")
#改变热图的深色背景为白色背景:
library(gplots) # 需要先安装这个包才能加载。
myheatcol = colorpanel(250,'red',"orange",'lemonchiffon')
TOMplot(plotDiss, selectTree, selectColors, main = "Network heatmap plot, selected genes", col=myheatcol)
这个图好像...没有太大的用处
5.2 可视化表征基因网络

研究找到的模块之间的关系,可以使用eigengene表征基因作为代表轮廓,通过特征基因相关性来量化模块的相似性。该包包含一个函数plotEigengeneNetworks,可以生成eigengene网络的摘要图。

# 重新计算模块的eigengenes
MEs = moduleEigengenes(datExpr, moduleColors)$eigengenes
# 提取体重的表型数据
weight = as.data.frame(datTraits$weight_g);
names(weight) = "weight"
# 加入到相应的模块
MET = orderMEs(cbind(MEs, weight))
#画图
sizeGrWindow(5,7.5);
par(cex = 0.9)
plotEigengeneNetworks(MET, "", marDendro = c(0,4,1,2), marHeatmap = c(3,4,1,2), cex.lab = 0.8, xLabelsAngle
                      = 90)

以上结果会生成特征模块与体重数据的聚类图和热图。要想拆分聚类图和热图,可以用以下代码实现。

sizeGrWindow(6,6);
par(cex = 1.0)
plotEigengeneNetworks(MET, "Eigengene dendrogram", marDendro = c(0,4,2,0),
                      plotHeatmaps = FALSE)
par(cex = 1.0)
plotEigengeneNetworks(MET, "Eigengene adjacency heatmap", marHeatmap = c(3,4,2,2),
                      plotDendrograms = FALSE, xLabelsAngle = 90)

从图中结果可知,体重与模块MEbrown、MEred、MEblue的关系更加密切。

6. 将网络导出到网络可视化软件

第六步是我们最想要的结果,也是每篇文献中最主要的一个图,就是hub基因的互作关系网络图。这步会告诉你如何将必要的数据导出,以供其他软件进行绘图,例如VisANT、Cytoscape。

6.0 参数设置与数据导入
setwd("~/Desktop/FemaleLiver-Data")
library(WGCNA)  #加载WGCNA包
options(stringsAsFactors = FALSE)  #开启多线程
lnames = load(file = "FemaleLiver-01-dataInput.RData");
lnames
lnames = load(file = "FemaleLiver-02-networkConstruction-auto.RData")
lnames
6.1 输出到VisANT软件所需的数据
TOM = TOMsimilarityFromExpr(datExpr, power = 6);
annot = read.csv(file = "GeneAnnotation.csv");
module = "brown";
probes = names(datExpr)
inModule = (moduleColors==module);
modProbes = probes[inModule];
modTOM = TOM[inModule, inModule];
dimnames(modTOM) = list(modProbes, modProbes)
vis = exportNetworkToVisANT(modTOM,
                            file = paste("VisANTInput-", module, ".txt", sep=""),
                            weighted = TRUE,
                            threshold = 0,
                            probeToGene = data.frame(annot$substanceBXH, annot$gene_symbol) )

因为棕色模块相当大,我们可以严格控制输出的hubgene的个数为30个以内在这个模块中。

nTop = 30;
IMConn = softConnectivity(datExpr[, modProbes]);
top = (rank(-IMConn) <= nTop)
vis = exportNetworkToVisANT(modTOM[top, top],
                            file = paste("VisANTInput-", module, "-top30.txt", sep=""),
                            weighted = TRUE,
                            threshold = 0,
                            probeToGene = data.frame(annot$substanceBXH, annot$gene_symbol) )

以上导出的数据可以用VisANT进行编辑,绘制互作网络。

6.2 输出到Cytoscape

Cytoscape 允许用户输入边缘文件和节点文件,允许用户指定例如连接权重和节点颜色。在这里,我们向 Cytoscape 展示了两个模块(红色和棕色模块)的输出。

TOM = TOMsimilarityFromExpr(datExpr, power = 6);
annot = read.csv(file = "GeneAnnotation.csv");
# 选择棕色和红色的模块
modules = c("brown", "red");
probes = names(datExpr)
inModule = is.finite(match(moduleColors, modules));
modProbes = probes[inModule];
modGenes = annot$gene_symbol[match(modProbes, annot$substanceBXH)];
# 选择相关的 TOM矩阵
modTOM = TOM[inModule, inModule];
dimnames(modTOM) = list(modProbes, modProbes)
# Export the network into edge and node list files Cytoscape can read
cyt = exportNetworkToCytoscape(modTOM,
                               edgeFile = paste("CytoscapeInput-edges-", paste(modules, collapse="-"), ".txt", sep=""),
                               nodeFile = paste("CytoscapeInput-nodes-", paste(modules, collapse="-"), ".txt", sep=""),
                               weighted = TRUE,
                               threshold = 0.02,
                               nodeNames = modProbes,
                               altNodeNames = modGenes,
                               nodeAttr = moduleColors[inModule])

参考:
官网教程
WGCNA分析流程详解
WGCNA分析,简单全面的最新教程
生信技能树视频:WGCNA分析原理与实践-part1
生信技能树视频:WGCNA分析原理与实践-part2
WGCNA,all in 还是DEGs?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容