呦呦切克鬧,WGCNA來一套

劉小澤寫于18.10.10
很早就見過它,但只是不明覺厲,直到昨天才開始認真了解

是這樣的:昨天上午看了一篇文獻,講冠心病的基因共表達分析,簡而言之就是把得到的幾千個變化比較大的基因和表型聯系起來,將他們放入幾十個模塊中,最后通過比較模塊、表型來確定要研究的那些基因,進而可以進行功能注釋之類的下游分析。對于樣本量大的研究(比如芯片、幾十個樣本的轉錄組、GWAS)來說,這么做是最快找到有價值基因的方法。

文章DOI:10.1186/s12872-016-0217-3
感覺對自己有幫助,就要拿來學習

搜集資料

當然,所有pdf資料以及實戰的教程數據都可以在公眾號回復“WGCNA”得到

這是一個全新的領域,但是對R不陌生,上手會省時一些

搜索WGCNA tutorial 第一個就是啦。最新的教程還是16年更新的,看來作者對自己的作品比較滿意啊,很少更新了現在

WGCNA官網

踏入新領域,首先就是要了解背景知識

WGCNA:全稱 Weighted correlation network analysis,中文名是加權基因共表達網絡分析

原來做幾個樣本的轉錄組,最后只要得到差異基因,再富集分析一下,就是一個經典的套路;但是樣本數量如果很多呢?背景基因就會很多,再用傳統的途徑獲得差異基因,往往會漏掉許多。WGCNA利用成千上萬個變化顯著的基因或全部基因的信息來篩選感興趣的基因集,并且聯系了表型的顯著性關聯分析

這樣做有兩個好處:一個是損失的基因少;另一個是把眾多的基因匯集到幾個基因集,和表型進行關聯,就不用做多重假設檢驗

  • Wighted加權/權重
    衡量重要程度,也就是不僅要看基因是否相關,還要看相關性大小

  • Network 網絡
    簡單網絡:點和線組成,大部分點之間都有線連接
    無尺度網絡:大部分節點很少連接,少部分點占據大量連接。基因的調控關系就是無尺度網絡

    簡單網絡與無尺度網絡

  • Correlation相關
    依據相關性得到模塊module ,指的是高度相關的基因,這些基因在不同組織或者一個生理過程中有相似的表達變化。每個模塊中總會有佼佼者,也就是“第一成分”,就是說這個基因和許多基因都有聯系,可以代表整體模塊。相當于北上廣這樣的核心地位

走進它的世界

第一步 數據輸入與初步處理

一般WGCNA需要15個樣本以上的數據,樣本越多結果越穩定

需要兩樣東西:表達矩陣datExpr表型矩陣datTraits

  • 表達矩陣:
    芯片數據的歸一化矩陣;
    轉錄組的表達矩陣(一般以RPKM為單位)【一般都是基因在行,樣品在列,后期還需要轉置的】

  • 表型矩陣:用于關聯分析,必須是數值型矩陣
    本身就是數值型:如長度、重量等,直接使用;
    本身不是數值型,如患病與否這樣的分類變量,需要用0-1表示(0表示沒有該屬性:患病,1表示有該屬性),構建0-1矩陣后再分析

    # 舉個例子
    ID    Sick Height Weight 
    sam1   1     1   2   
    sam2   1     2   7 
    sam3   0     10  22 
    sam4   0     NA  31  
    sam5   0     14  19   
    
wkdir <- "."
setwd(wkdir)
library(WGCNA)
options(stringsAsFactors = FALSE)
femData = read.csv("LiverFemale3600.csv")
#dim(femData)
names(femData) #看下列名
進行轉置:設置初步的表達矩陣:樣本為行,觀測為列
datExpr0 = as.data.frame(t(femData[, -c(1:8)]))
names(datExpr0) = femData$substanceBXH
rownames(datExpr0) = names(femData)[-c(1:8)]
檢查基因和樣本是否有太多的缺失值【太多就去掉】
gsg = goodSamplesGenes(datExpr0, verbose = 3)
gsg$allOK # 返回TRUE則繼續
# (可選)如果存在太多的缺失值
if (!gsg$allOK)
{
  # 把含有缺失值的基因或樣本打印出來
  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 = ", ")));
  # 去掉那些缺失值
  datExpr0 = datExpr0[gsg$goodSamples, gsg$goodGenes]
}
對樣本進行聚類,檢測異常值
if(T){
  sampleTree = hclust(dist(datExpr0), method = "average")
  pdf(file = "sampleClustering.pdf", width = 12, height = 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)
  # 結果可以看到,F2_221是一個異常值
  abline(h = 15, col = "red") #先畫一條輔助線
  dev.off()
}
樣本進行聚類
去除異常值,得到過濾后的表達矩陣
# 把高于15的切除
clust = cutreeStatic(sampleTree, cutHeight = 15, minSize = 10)
table(clust) # 0代表切除的,1代表保留的
keepSamples = (clust==1)
datExpr = datExpr0[keepSamples, ]
開始設置表型矩陣=》加載表型信息

再次注意:所有的表型信息都要用數值來表示在各個樣本中的大小
(比如:體重、長度、肥胖度等都要量化)

traitData = read.csv("ClinicalTraits.csv")
#dim(traitData)
names(traitData)
# 去掉不需要的信息,得到全部樣本的表型矩陣
allTraits = traitData[, -c(31, 16)] #去掉'note'、'comments'
allTraits = allTraits[, c(2, 11:36) ] # 去掉中間的日期之類的
dim(allTraits)
names(allTraits)
得到部分表型矩陣=》表達矩陣有哪些樣本,表型矩陣就有哪些樣本
femaleSamples = rownames(datExpr)
traitRows = match(femaleSamples, allTraits$Mice)
# 把原來的第一列Mice變成行名
datTraits = allTraits[traitRows, -1]
rownames(datTraits) = allTraits[traitRows, 1]
collectGarbage() #釋放內存空間

到這里為止,得到了所有樣本的表達矩陣和表型矩陣,在進一步構建網絡、檢測模塊之前,先看下表型和樣本的相關性

針對去除異常值的表達矩陣進行聚類分析
sampleTree2 = hclust(dist(datExpr), method = "average")
# 用顏色表示表型在各個樣本的表現: 白色表示低,紅色為高,灰色為缺失
traitColors = numbers2colors(datTraits, signed = FALSE)
# 把樣本聚類和表型熱圖繪制在一起
if(T){
  pdf(file = "Sample dendrogram and trait heatmap.pdf", width = 18, height = 10)
  plotDendroAndColors(sampleTree2, traitColors,
                      groupLabels = names(datTraits),
                      main = "Sample dendrogram and trait heatmap")
  dev.off()
}
save(datExpr, datTraits, file = "FemaleLiver-01-dataInput.RData")
樣本聚類和表型熱圖

第二步 網絡分析

構建網絡、檢測協同表達的基因模塊(非常重要的一步!)

實現構建網絡有3種方法:(3選1即可)
1.One-step;
2.Step-by-step 支持自定義一些參數;
3.Block-wise network construction 針對大型數據

加載之前保存的RData

lnames = load(file = "FemaleLiver-01-dataInput.RData")

這里采用一步分析法

篩選軟閾值(soft thresholding power)

原則是使構建的網絡更符合無標度網絡特征

#設置一系列軟閾值(默認1到30)
powers = c(c(1:10), seq(from = 12, to=20, by=2))
#幫助用戶選擇合適的軟閾值,進行拓撲網絡分析
#需要輸入表達矩陣、設置的閾值范圍、運行顯示的信息程度(verbose=0不顯示任何信息)
sft = pickSoftThreshold(datExpr, powerVector = powers, verbose = 5)

sft結果有兩列,其中powerEstimate返回最佳的軟閾值beta值。這里的結果是6,表示從6達到高閾值以后,圖形曲線開始變平,就是說:到達閾值6時網絡拓撲結構連通的就差不多了,夠本了!具體見下面做出的圖(左一)來理解。實際使用并不需要知道具體值

畫出結果 =》橫軸是Soft threshold (power)
(左圖)縱軸是無標度網絡的評估參數(相關系數的平方),數值越高,網絡越符合無標度特征 (non-scale)
(右圖)縱軸是基因模塊中所有基因鄰接函數的均值

if(T){
  pdf(file = "Soft threshold.pdf", width = 18, height = 10)
  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"))
  #注意這里的-sign(sft$fitIndices[,3])中sign函數,它把正數、負數分別轉為1、-1
  text(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
       labels=powers,cex=cex1,col="red")
  # 設置篩選標準h=r^2^=0.9。這里的0.9是個大概的數,就是看左圖軟閾值6大概對應的位置
  abline(h=0.90,col="red")
  #看一下Soft threshold與平均連通性
  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")
  dev.off()
}
得到軟閾值
一步構建網絡[關鍵一步!]

幾千個基因組歸類成了幾十個模塊

計算基因間的鄰接性,根據鄰接性計算基因間的相似性,然后算出基因間的相異性系數,并因此得到基因間的系統聚類樹
按照混合動態剪切樹的標準,設置每個基因模塊最少的基因數目為30
確定基因模塊后,再次分析,依次計算每個模塊的特征向量值
對模塊進行聚類分析,將距離較近的模塊合并為新的模塊
power就是上面計算得到的軟閾值

net = blockwiseModules(datExpr, power = 6,
                       TOMType = "unsigned", minModuleSize = 30,
                       reassignThreshold = 0, mergeCutHeight = 0.25,
                       numericLabels = TRUE, pamRespectsDendro = FALSE,
                       saveTOMs = TRUE,
                       saveTOMFileBase = "femaleMouseTOM",
                       verbose = 3)
# 顯示模塊數量以及各自包含的基因數目
# 0表示未分入任何模塊的基因
# 1是最大的模塊,往后依次降序排列,分別對應各自模塊的基因
table(net$colors)
模塊可視化=》聚類樹

將每個模塊對應的基因數轉換成顏色單位, 灰色默認是無法歸類于任何模塊的那些基因

mergedColors = labels2colors(net$colors)

先畫聚類,后畫顏色

if(T){
  pdf(file = "DendroAndColors.pdf", width = 18, height = 10)
  plotDendroAndColors(net$dendrograms[[1]], mergedColors[net$blockGenes[[1]]],
                      "Module colors",
                      dendroLabels = FALSE, hang = 0.03,
                      addGuide = TRUE, guideHang = 0.05)
  dev.off()
}
模塊聚類樹

保存數據

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")

第三步 模塊聯系表型信息

看看哪些表型的哪些模塊是自己感興趣的(一般選熱圖顏色深的)

這樣初步表明該模塊中基因可能是有研究價值的;
下一步,進行一個驗證,看看這個模塊中基因與表型、模塊的相關性,看看與模塊相關的基因是不是也與表型相關

rm(list = ls())
load(file = "FemaleLiver-01-dataInput.RData")
load(file = "FemaleLiver-02-networkConstruction-auto.RData")
模塊關聯表型
# 得到基因、樣本數量
nGenes = ncol(datExpr)
nSamples = nrow(datExpr)
# 用color labels重新計算MEs(Module Eigengenes:模塊的第一主成分)
MEs0 = moduleEigengenes(datExpr, moduleColors)$eigengenes
MEs = orderMEs(MEs0)
moduleTraitCor = cor(MEs, datTraits, use = "p") #(這是重點)計算ME和表型相關性
moduleTraitPvalue = corPvalueStudent(moduleTraitCor, nSamples)
對moduleTraitCor畫熱圖,看結果挑選自己感興趣的模塊進行下游分析
if(T){
  pdf(file = "labeledHeatmap.pdf", width = 18, height = 10)
  # 設置熱圖上的文字(兩行數字:第一行是模塊與各種表型的相關系數;
  # 第二行是p值)
  # signif 取有效數字
  textMatrix = paste(signif(moduleTraitCor, 2), "\n(",
                     signif(moduleTraitPvalue, 1), ")", sep = "")
  dim(textMatrix) = dim(moduleTraitCor)
  par(mar = c(6, 8.5, 3, 3))
  # 然后對moduleTraitCor畫熱圖
  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"))
  dev.off()
}
模塊關聯表型

每種表型都有和它非常相關的模塊,因此某個模塊可以作為某個表型的代表(signature),對于非常相關的模塊,比如weight表型和brown模塊,顏色最深。那么里面的基因是什么?于是進行感興趣表型中核心模塊的基因分析

計算基因與模塊的相關性矩陣(MM: Module Membership)
# 把各個module的名字提取出來(從第三個字符開始),用于一會重命名
modNames = substring(names(MEs), 3)
# 得到矩陣
geneModuleMembership = as.data.frame(cor(datExpr, MEs, use = "p"))
# 矩陣t檢驗
MMPvalue = as.data.frame(corPvalueStudent(as.matrix(geneModuleMembership), nSamples))
# 修改列名
names(geneModuleMembership) = paste("MM", modNames, sep="")
names(MMPvalue) = paste("p.MM", modNames, sep="")

計算基因與表型的相關性矩陣(GS: Gene Significance)
# 先將感興趣表型weight提取出來,用于計算矩陣
weight = as.data.frame(datTraits$weight_g)
names(weight) = "weight"
# 得到矩陣
geneTraitSignificance = as.data.frame(cor(datExpr, weight, use = "p"))
# 矩陣t檢驗
GSPvalue = as.data.frame(corPvalueStudent(as.matrix(geneTraitSignificance), nSamples))
# 修改列名
names(geneTraitSignificance) = paste("GS.", names(weight), sep="")
names(GSPvalue) = paste("p.GS.", names(weight), sep="")
合并兩個相關性矩陣,找到和模塊、表型都高度相關的基因
if(T){
  module = "brown"
  pdf(file = paste0(module,"-MM-GS-scatterplot.pdf"), width = 10, height = 10)
  column = match(module, modNames) #找到目標模塊所在列
  moduleGenes = moduleColors==module #找到模塊基因所在行
  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)
  dev.off()
}
模塊、表型都高度相關的基因

圖中看到,MM和GS高度正相關,因此說明和表型高度相關的基因,在與表型相關模塊中也是核心元素。

另外,也可以探索weight表型中其他的模塊,比如第一個顏色很淺的magenta模塊,它的MM和GS整體負相關


負相關的基因

第四步 網絡可視化

【針對基因】熱圖的方式展示加權網絡,每行每列代表一個基因

還能表示鄰近關系和拓撲重疊,淺顏色表示關系弱,深顏色表示關系強

基因的聚類分析和模塊顏色畫在頂部和左側

rm(list = ls())
load(file = "FemaleLiver-01-dataInput.RData")
load(file = "FemaleLiver-02-networkConstruction-auto.RData")
nGenes = ncol(datExpr)
nSamples = nrow(datExpr)

選擇400個基因畫圖

if(T){
  nSelect = 400
  set.seed(10)
  # 計算拓撲重疊(TOM: Topological Overlap Matrix)
  # 這個過程先計算了鄰接矩陣,后把鄰接矩陣轉換為拓撲重疊矩陣,
  # 降低了噪音和假相關,獲得距離矩陣dissTOM
  dissTOM = 1-TOMsimilarityFromExpr(datExpr, power = 6)
  select = sample(nGenes, size = nSelect)
  selectTOM = dissTOM[select, select]
  # 再計算基因之間的距離樹(對于基因的子集,需要重新聚類)
  selectTree = hclust(as.dist(selectTOM), method = "average")
  selectColors = moduleColors[select]
  
  pdf(file = paste0("Sub400-netheatmap.pdf"), width = 10, height = 10)
  plotDiss = selectTOM^7
  diag(plotDiss) = NA #將對角線設成NA,在圖形中顯示為白色的點,更清晰顯示趨勢
  TOMplot(plotDiss, selectTree, selectColors, main = "Network heatmap plot, selected genes")
  dev.off()
}
基因網絡可視化

選擇全部基因畫圖(耗時較久,生成的文件很大)

結果可以看到各個區塊的顏色差異,沿著對角線的深色區塊就是模塊Module

if(T){
  pdf(file = "All-netheatmap.pdf", width = 10, height = 10)
  plotTOM = dissTOM^7
  diag(plotTOM) = NA
  TOMplot(plotTOM, geneTree, moduleColors, main = "Network heatmap plot, all genes")
  dev.off()
}
【針對模塊與表型】展示模塊與表型的相關性

重新計算模塊的基因樣本相關矩陣(Eigengenes就是基因和樣本的相關矩陣)

MEs = moduleEigengenes(datExpr, moduleColors)$eigengenes
# 將weight表型信息從trait中提取出來
weight = as.data.frame(datTraits$weight_g)
names(weight) = "weight"
# 把weight表型添加到之前計算的ME矩陣中,并排序
MET = orderMEs(cbind(MEs, weight))

# 畫圖=》meta-modules(模塊的聚類圖加上模塊與表型的熱圖)
# marDendro/marHeatmap 設置下、左、上、右的邊距
if(T){
  pdf(file = "Eigengene-dengro-heatmap.pdf", width = 10, height = 15)
  par(cex = 0.9)
  plotEigengeneNetworks(MET, "", marDendro = c(0,4,1,2), marHeatmap = c(4,4,1,2), cex.lab = 0.8, xLabelsAngle
                        = 90)
  dev.off()
}
模塊表型可視化

圖中可以看到,red、blue、brown模塊是高度相關的,并且它們的相關性比各自和weight表型的相關性還大;salmon和weight的相關性也比較強,但是加入red、blue、brown的meta-modules陣營還不夠格

當然分開畫也是可以的

if(T){
  pdf(file = "Eigengene-dendrogram.pdf", width = 10, height = 10)
  par(cex = 1.0)
  plotEigengeneNetworks(MET, "Eigengene dendrogram", marDendro = c(0,4,2,0),
                        plotHeatmaps = FALSE)
  dev.off()
  pdf(file = "Eigengene-heatmap.pdf", width = 10, height = 10)
  par(cex = 1.0)
  plotEigengeneNetworks(MET, "Eigengene adjacency heatmap", marHeatmap = c(4,5,2,2),
                        plotDendrograms = FALSE, xLabelsAngle = 90)
  dev.off()
}

第五步 導出網絡

準備過程
# 重新計算拓撲重疊矩陣
TOM = TOMsimilarityFromExpr(datExpr, power = 6)
# 選擇導出模塊
module = "brown"
# 選擇模塊中基因/探針
probes = names(datExpr)
inModule = (moduleColors==module)
modProbes = probes[inModule]
# 選擇相關模塊的拓撲重疊矩陣
modTOM = TOM[inModule, inModule]
dimnames(modTOM) = list(modProbes, modProbes)
導出到VisANT
vis = exportNetworkToVisANT(modTOM,
                            file = paste("VisANTInput-", module, ".txt", sep=""),
                            weighted = TRUE,
                            threshold = 0)

感覺基因太多,可以截取部分(比如前30)
nTop = 30
IMConn = softConnectivity(datExpr[, modProbes])
top = (rank(-IMConn) <= nTop)
submodTOM <- modTOM[top, top] #然后用submodTOM代替前面的modTOM導出
導出到Cytoscape
modules = c("brown", "red")
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,
                               nodeAttr = moduleColors[inModule])
# 同理,感覺基因太多可以用submodTOM代替modTOM

寫在最后

這只是一個基礎的流程,為了熟悉熟悉流程。只是針對一個大樣本;如果有多個來源不同的大樣本進行分析,還需要參考官網的第二部分教程

得到了模塊中的基因后,就可以進行GO、KEGG的富集分析,可以挖掘模塊中關鍵基因,然后預測基因功能


歡迎關注我們的公眾號~_~  
我們是兩個農轉生信的小碩,打造生信星球,想讓它成為一個不拽術語、通俗易懂的生信知識平臺。需要幫助或提出意見請后臺留言或發送郵件到Bioplanet520@outlook.com

Welcome to our bioinfoplanet!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容