• wgcna 原文复现 小胶质细胞亚群在脑发育时髓鞘形成的作用 microglial


    手把手10分文章WGCNA复现:小胶质细胞亚群在脑发育时髓鞘形成的作用

    Original 生信技能树 生信技能树 2020-01-09 14:2

    Hi大家好,我是老米!生信入门一个月,感谢生信技能树平台。这是我的第3篇Markdown。不知道多少人还记得我的前两个投稿:

    现在继续完成生信技能树的作业题:重复一篇WGCNA分析的文章。WGCNA学习教程:一文学会WGCNA分析。

    复现的文献:A novel microglial subset plays a key role in myelinogenesis in developing brain。EMBO J,好杂志。

    该文章对五个处理组,共17个老鼠:

    • orange represents neonatal CD11c+ microglia (n = 4),

    • green neonatal CD11c microglia (n = 4),

    • blue EAE CD11c+ microglia (n = 3),

    • purple EAE CD11c microglia (n = 3),

    • black adult microglia (n = 3).

    其实就是 neonatal(新生的) 和 EAE的Microglia,还有CD11C阳性和阴性,然后和成年小鼠的Microglia进行比较。这些样本进行了RNASeq测序,数据在GEO可供下载:https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE78809。当然我偷了个懒,该文章Supplemental material提供了整理之后的csv矩阵,大概1万3千个基因。

    作者进行了WGCNA分析,以此证明小胶质细胞的作用及寻找关键信号通路及基因(嗯,估计这个实验室后续还有大文章出来)。

    组学及生信分析的篇幅占了整个文章的一半以上。在此,仅重复文章的Figure3。

           其实我跌跌撞撞学了WGCNA半个月,大概了解了这个原理,现在还一知半解,对很多细节摸索了很久,头很大。下面进入正题,请大家一起跟着我头大。

    1.数据处理

    1. rm(list = ls())
    2. dev.off()
    3. library(WGCNA)# 偷懒,读取作者给出的附件的表达矩阵
    4. norm.counts <read.csv("Dataset_EV2.csv",header = T,sep = ",") ##original counts
    5. rownames(norm.counts)<-norm.counts[,1]
    6. norm.counts <- norm.counts[,2:18]
    7. save(norm.counts,file = "norm.counts.Rdata")
    1. ## 处理表型信息,就是老鼠的分组信息
    2. <- colnames(norm.counts)
    3. library(stringr)
    4. str_tmp=as.data.frame(str_split(a,"[_]",simplify = T))
    5. rownames(str_tmp) <- colnames(norm.counts)
    6. colnames(str_tmp) <- c("group","sampleRep")
    1. datTraits <- str_tmp
    2. datTraits$groupNo <- c(rep(1,3),rep(2,4),rep(3,4),rep(4,3),rep(5,3)) 
    1. ###数据初步处理完成
    2. ## 筛选中位绝对偏差前75%的基因,取MAD大于0.3
    3. ## 筛选后会降低运算量,也会失去部分信息
    4. ## 也可不做筛选,使MAD大于0即可
    5. norm.counts <- log2(norm.counts)  ##注意我在这里进行了log2,因为我发现如果不log的话,出现了个很有意思的现象,请您往下看
    6. m.mad <- apply(norm.counts,1,mad)
    7. dataExprMad <- norm.counts[which(m.mad > max(quantile(m.mad, probs=seq(010.25))[2],0.3)),] #25%  = 0.22
    8. datExpr0 <as.data.frame(t(dataExprMad))
    1. ##最终取到8223个基因。
    2. ###########start handling the data
    3. ##看看有没有为空的值,需要剔除。这里下载的都是作者处理好的,基本没问题。
    4. gsg <- goodSamplesGenes(datExpr0,verbose = 3)
    5. gsg$allOK
    6. if (!gsg$allOK){
    7.   # Optionally, print the gene and sample names that were removed:
    8.   if (sum(!gsg$goodGenes)>0)
    9.     printFlush(paste("Removing genes:", paste(names(datExpr0)[!gsg$goodGenes],
    10.                                               collapse = ", ")));
    11.   if (sum(!gsg$goodSamples)>0)
    12.     printFlush(paste("Removing samples:",
    13.                      paste(rownames(datExpr0)[!gsg$goodSamples], collapse = ", ")));
    14.   # Remove the offending genes and samples from the data:
    15.   datExpr0 = datExpr0[gsg$goodSamples, gsg$goodGenes]
    16. }
    17. gsg <- goodSamplesGenes(datExpr0,verbose = 3)
    18. gsg$allOK
    19. ###画个树看看样本有没有离群值!!!
    20. if(T){
    21.   # Plot a line to show the cut
    22.   sampleTree <- hclust(dist(datExpr0),method = "average")
    23.   par(cex=.6)
    24.   par(mar=c(0,4,2,0))
    25.   plot(sampleTree, main = "Sample clustering to detect outliers", sub = "",
    26.        xlab = "",cex.lab = 1.5, cex.axis =1.5, cex.main=2
    27.   )
    28. }
    29. ##然后保存数据
    30. dim(datExpr0) ##178222
    31. datExpr <- datExpr0
    32. nGenes <- ncol(datExpr)
    33. nSamples <- nrow(datExpr)
    34. save(nGenes,nSamples,datExpr,datTraits,file="input.Rdata")

    结果如图:

           这结果挺好的,符合实验设计,都聚类好了。但是!但是如果不对原始数值进行log2处理,会出现一个outlier老鼠,如图:

           看到没,那个新生的NEO1号鼠有点调皮!他超脱于所有老鼠之上,统领其他所有老鼠!这要么是问题少年,要么是智商超群,比如科大少年班的那种!而我大概深究了一下,控制这个离群值的大概是500个基因,哈哈哈。。。

    2. MDS分析

           专业名词叫多维标度法(Multidimensional Scaling)MDS,是一种维数缩减方法,把高维的数据点映射到一个低维的流形上;同时也是一种可视化方法,实践中通常利用2D或3D的MDS 结果观察(投影后)点的分布和聚集来研究数据的性质。实际上你也可以把它看做是PCA分析,反正都是看样本间的相关性计算距离远近。

    说人话叫做:通过基因表达log2组间差异,看看这17个老鼠是否能够分到一个类别,比如成年鼠归到一类,EAE归到一类,新生鼠归到一类。和上面的有点类似,又不完全一样。

           参考学习了stat的视频,也参考了他提供的代码。如下:

    1. rm(list = ls())
    2. load(file = 'input.Rdata')
    3. log2.data.matrix <as.data.frame(t(datExpr))
    4. ## now create an empty distance matrix
    5. log2.distance.matrix <- matrix(0,
    6.                                nrow=ncol(log2.data.matrix),
    7.                                ncol=ncol(log2.data.matrix),
    8.                                dimnames=list(colnames(log2.data.matrix),
    9.                                              colnames(log2.data.matrix)))
    10. ## now compute the distance matrix using avg(absolute value(log2(FC)))
    11. for(i in 1:ncol(log2.distance.matrix)) {
    12.   for(j in 1:i) {
    13.     log2.distance.matrix[i, j] <-
    14.       mean(abs(log2.data.matrix[,i] - log2.data.matrix[,j]))
    15.   }
    16. }
    17. ## do the MDS math (this is basically eigen value decomposition)
    18. ## cmdscale() is the function for "Classical Multi-Dimensional Scalign"
    19. mds.stuff <- cmdscale(as.dist(log2.distance.matrix),
    20.                       eig=TRUE,
    21.                       x.ret=TRUE)
    22. save(mds.stuff,file = "step7_MDS.Rdata")
    23. ## calculate the percentage of variation that each MDS axis accounts for...
    24. mds.var.per <- round(mds.stuff$eig/sum(mds.stuff$eig)*1001)
    25. ## now make a fancy looking plot that shows the MDS axes and the variation:
    26. mds.values <- mds.stuff$points
    27. mds.data <data.frame(Sample=rownames(mds.values),
    28.                        X=mds.values[,1],
    29.                        Y=mds.values[,2])
    30. ## 然后画图
    31. library(ggpubr)
    32. library(ggplot2)
    33. groups <- datTraits$group
    34. png("figures/step7_MDS_logfc.png",width = 800,height=600)
    35. ggplot(mds.data, aes(x=X, y=Y, label=Sample,col=groups)) + 
    36.   geom_point(size = 10, alpha = 0.8+
    37.   theme(panel.grid.minor = element_blank()) +
    38.   coord_fixed() + theme_bw()+
    39.   ggtitle("MDS plot using avg(logFC) as the distance")+
    40.   xlab(paste("Leading logFC dim1 ", mds.var.per[1], "%", sep="")) +
    41.   ylab(paste("Leading logFC dim2 ", mds.var.per[2], "%", sep="")) +
    42.   ggtitle("MDS plot using avg(logFC) as the distance")
    43. dev.off()

    结果如下:

           嗯,,,结果表示完美!别问我为什么要先做这个图,因为它好看,我忍不住!

    点评:老米在这里开始秀技术了,实际上大家随便跑一下PCA分析即可,暂时无需深入写这么长代码!

           下面正式进入WGCNA分析。

    3. 计算beta值

      这个没啥好讲的,代码如下:

    1. rm(list = ls())
    2. library(WGCNA)
    3. load(file = "input.Rdata")
    4. dim(datExpr)
    5. #################################################
    6. if(T){
    7.         powers = c(c(1:10), seq(from = 12to=30by=2))
    8.         # Call the network topology analysis function
    9.         sft = pickSoftThreshold(datExpr, powerVector = powers, verbose = 5)
    10.         png("figures/step2-beta-value.png",width = 800,height = 600)
    11.         # Plot the results:
    12.         ##sizeGrWindow(95)
    13.         par(mfrow = c(1,2));
    14.         cex1 = 0.9;
    15.         # Scale-free topology fit index as a function of the soft-thresholding power
    16.         plot(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
    17.              xlab="Soft Threshold (power)",ylab="Scale Free Topology Model Fit,signed R^2",type="n",
    18.              main = paste("Scale independence"));
    19.         text(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
    20.              labels=powers,cex=cex1,col="red");
    21.         # this line corresponds to using an R^2 cut-off of h
    22.         abline(h=0.9,col="red")
    23.         # Mean connectivity as a function of the soft-thresholding power
    24.         plot(sft$fitIndices[,1], sft$fitIndices[,5],
    25.              xlab="Soft Threshold (power)",ylab="Mean Connectivity"type="n",
    26.              main = paste("Mean connectivity"))
    27.         text(sft$fitIndices[,1], sft$fitIndices[,5], labels=powers, cex=cex1,col="red")
    28.         dev.off()
    29. }
    30. sft$powerEstimate  ## beta=22 SCI文章里面用了20
    31. save(sft,file = "step2_beta_value.Rdata")

    4. 采用一步法构建加权共表达网络

    (weight co-expression network)

    1. rm(list = ls())
    2. library(WGCNA)
    3. load(file = "input.Rdata")
    4. load(file = "step2_beta_value.Rdata")
    5. enableWGCNAThreads()
    6. if(T){
    7.   net = blockwiseModules(
    8.     datExpr,
    9.     power = sft$powerEstimate,
    10.     maxBlockSize = nGenes,
    11.     TOMType = "unsigned", minModuleSize = 30,
    12.     reassignThreshold = 0, mergeCutHeight = 0.28, ## 注意这个0.28
    13.     numericLabels = TRUE, pamRespectsDendro = FALSE,
    14.     saveTOMs = F,
    15.     verbose = 3
    16.   )
    17.   table(net$colors) 
    18. }
    19. ##模块可视化,画那个传说中的树
    20. if(T){
    21.   # Convert labels to colors for plotting
    22.   moduleColors=labels2colors(net$colors)
    23.   table(moduleColors)
    24.   # Plot the dendrogram and the module colors underneath
    25.   png("figures/step3-genes-modules.png",width = 800,height = 600)
    26.   plotDendroAndColors(net$dendrograms[[1]], moduleColors[net$blockGenes[[1]]],
    27.                       "Module colors",
    28.                       dendroLabels = FALSE, hang = 0.03,
    29.                       addGuide = TRUE, guideHang = 0.05)
    30.   dev.off()
    31. }
    32. save(net,moduleColors,file = "step3_genes_modules.Rdata")

           

    结果如下:

            这里需要停顿一下:SCI文章只取到8个模块,图注说用了12691个基因(被我发现全部加起来也才9999,没错!9999个基因)。事实上,能够分这么少模块,我不知道作者参数细节。有两个参数特别影响模块大小:

    • 一个是minModuleSize,表示每个模块里面最少放多少个基因,这很好理解,设定越大,模块越少;

    • 另一个是mergeCutHeight,这个参数表示你在哪里砍树。值设定越小,树枝越多,通常是0.25。

    google一下,发现这么一个说法:

    I am not aware of a principle from which

          这里,我的mergeCutHeight = 0.28,最终取到13个模块!

    5. 模块与基因与表型

    5.1 模块和老鼠表型对应

    这是关键,其实就是开始解读这些关联的基因群对老鼠表型的影响,比如敲除CDC11之后的老鼠,哪些信号通路激活或抑制,EAE的老鼠哪些基因激活?等等等。

    1. rm(list = ls())
    2. library(WGCNA)
    3. load(file = "input.Rdata")
    4. load(file = "step2_beta_value.Rdata")
    5. load(file = "step3_genes_modules.Rdata")
    6. if(T){
    7.   nGenes = ncol(datExpr)
    8.   nSamples = nrow(datExpr)
    9.   design <- model.matrix(~0+datTraits$group)
    10.   colnames(design)= levels(datTraits$group) ## get the group
    11.   MES0 <- moduleEigengenes(datExpr,moduleColors)$eigengenes
    12.   MEs = orderMEs(MES0)
    13.   moduleTraitCor <- cor(MEs,design,use = "p")
    14.   moduleTraitPvalue <- corPvalueStudent(moduleTraitCor,nSamples)
    15.   textMatrix = paste(signif(moduleTraitCor,2),"\n(",
    16.                      signif(moduleTraitPvalue,1),")",sep = "")
    17.   dim(textMatrix)=dim(moduleTraitCor)
    18.   png("figures/step4-Module-trait-relationship.png",width = 800,height = 1200,res = 120)
    19.   par(mar=c(68.533))
    20.   labeledHeatmap(Matrix = moduleTraitCor,
    21.                  xLabels = colnames(design),
    22.                  yLabels = names(MEs),
    23.                  ySymbols = names(MEs),
    24.                  colorLabels = FALSE,
    25.                  colors = blueWhiteRed(50),
    26.                  textMatrix = textMatrix,
    27.                  setStdMargins = FALSE,
    28.                  cex.text = 0.5,
    29.                  zlim = c(-1,1),
    30.                  main = paste("Module-trait relationships"))
    31.   dev.off()
    32.   save(design,file = "step4_design.Rdata")
    33. }

     

    通过模块与各种表型的相关系数,可发现自己感兴趣的模块。如图:

    可以看到有些模块与成年鼠关联,有些与EAE相关性很高。和原SCI的图有点像。

    5.2 各模块与表型相关性bar图

    就是上面的图转化成bar图。

    1. if(T){
    2.   mes_group <merge(MEs,datTraits,by="row.names") # 小技巧,可以通过rowname进行merge
    3.   ##写了个画图的function
    4.   library(gplots)
    5.   library(ggplot2)
    6.   library(ggpubr)
    7.   library(grid)
    8.   library(gridExtra) 
    9.   draw_ggboxplot <function(data,gene="P53",group="group"){
    10.     #print(gene)
    11.     ggboxplot(data,x=group, y=gene,
    12.               ylab = sprintf("Expression of %s",gene),
    13.               xlab = group,
    14.               fill = group,
    15.               palette = "jco",
    16.               #add="jitter",
    17.               legend = ""+stat_compare_means()
    18.   }
    19.   ###开始批量画boxplot
    20.   colorNames = names(MEs)
    21.   png("figures/step4-expression-group.png",width = 800,height=2000,res = 120)
    22.   #par(mfrow=c(ceiling(length(colorNames)/2),2))
    23.   p <- lapply(colorNames,function(x) {
    24.     draw_ggboxplot(mes_group,gene= x,group="group")
    25.   })
    26.   do.call(grid.arrange,c(p,ncol=2))
    27.   dev.off()
    28. }

    mes_group <- merge(MEs,datTraits,by="row.names") # 小技巧,可以通过rowname进行merge 

    部分结果如下:

    5.3 模块与基因的相关性

    1. if(T){
    2.   modNames = substring(names(MEs), 3)
    3.   geneModuleMembership = as.data.frame(cor(datExpr, MEs, use = "p"))
    4.   ## 算出每个模块跟基因的皮尔森相关系数矩阵
    5.   ## MEs是每个模块在每个样本里面的值
    6.   ## datExpr是每个基因在每个样本的表达量
    7.   MMPvalue = as.data.frame(corPvalueStudent(as.matrix(geneModuleMembership), nSamples))
    8.   names(geneModuleMembership) = paste("MM", modNames, sep="")
    9.   names(MMPvalue) = paste("p.MM", modNames, sep="")
    10.   geneTraitSignificance <as.data.frame(cor(datExpr,datTraits$groupNo,use = "p"))
    11.   GSPvalue <as.data.frame(corPvalueStudent(as.matrix(geneTraitSignificance),nSamples))
    12.   names(geneTraitSignificance)<- paste("GS.",names(datTraits$group),sep = "")
    13.   names(GSPvalue)<-paste("GS.",names(datTraits$group),sep = "")
    14.   #selectModule<-c("blue","green","purple","grey")  ##可以选择自己喜欢的模块
    15.   selectModule <- modNames  ## 也可以批量作图
    16.   png("figures/step4-Module-trait-significance.png",width = 800,height=2000,res = 120)
    17.   par(mfrow=c(ceiling(length(selectModule)/2),2)) #批量作图开始
    18.   for(module in selectModule){
    19.     column <- match(module,selectModule)
    20.     print(module)
    21.     moduleGenes <- moduleColors==module
    22.     verboseScatterplot(abs(geneModuleMembership[moduleGenes, column]),
    23.                        abs(geneTraitSignificance[moduleGenes, 1]),
    24.                        xlab = paste("Module Membership in", module, "module"),
    25.                        ylab = paste("Gene significance for", module, "module"),
    26.                        main = paste("Module membership vs. gene significance\n"),
    27.                        cex.main = 1.2, cex.lab = 1.2, cex.axis = 1.2col = module)
    28.   }
    29.   dev.off()
    30. }

     

     

     

    截取部分如下:

    5.4 关注感兴趣的模块,导出基因进行GO分析

     

     

     

     

    1. rm(list = ls())
    2. library(WGCNA)
    3. load(file = 'input.Rdata')
    4. load(file = "step2_beta_value.Rdata")
    5. load(file = "step3_genes_modules.Rdata")
    6. load(file = "step4_design.Rdata")
    7. load(file="step4_datTraits.Rdata")
    8. table(moduleColors)
    9. group_g <data.frame(gene=colnames(datExpr),
    10.                       group=moduleColors)
    11. write.csv(group_g,file = "figures/group_g.csv") ## 导出了对应模块所有基因
    12. # 选择mouse的基因组进行注释及ID转化啥的,如果是人的,另有R包
    13. if(!require("clusterProfiler")) BiocManager::install("clusterProfiler",ask = F,update = F)
    14. library(clusterProfiler)
    15. if(!require("org.Mm.eg.db")) BiocManager::install("org.Mm.eg.db",ask = F,update = F)
    16. library(org.Mm.eg.db)
    17. tmp <- bitr(group_g$gene,fromType = "ENSEMBL",
    18.             toType = "ENTREZID",
    19.             OrgDb = "org.Mm.eg.db")
    20. de_gene_cluster <merge(tmp,group_g,by.x="ENSEMBL",by.y="gene")
    21. table(de_gene_cluster$group)
    22. ###run go analysis
    23. formula_res <- compareCluster(
    24.   ENTREZID~group,
    25.   data = de_gene_cluster,
    26.   fun = "enrichGO",
    27.   OrgDb = "org.Mm.eg.db",
    28.   style="margin: 0px; padding: 0px; font-size: inherit; line-height: inherit; color: rgb(80, 161, 79); overflow-wrap: inherit !important; word-break: inherit !important;">"BP",
    29.   pAdjustMethod = "BH",
    30.   pvalueCutoff = 0.01,
    31.   qvalueCutoff = 0.05
    32. )
    33. lineage1_ego <-simplify(
    34.   formula_res,
    35.   cutoff=0.5,
    36.   by="p.adjust",
    37.   select_fun=min
    38. )
    39. save(group_g,formula_res,lineage1_ego,file="step5_GOananlysis.Rdata")
    40. #出图
    41. pdf("figures/step5_Microglia_GO_term_DE.pdf",width = 15,height = 15)
    42. dotplot(lineage1_ego,showCategory=10)
    43. dev.off()
    44. write.csv(lineage1_ego@compareClusterResult,
    45.           file="figures/Microglia_GO_term_DE.csv")

     

     

    GO结果分析如下:

           

    通过与上面的几个图表配合,发现EAE鼠与炎症通路/免疫相关,而新生鼠的胶质细胞则是cell cycle/胶质细胞分化/神经细胞发育/轴树突形成通路相关。与原SCI分析相符,与预期相符。

    5.5 画WGCNA的标配热图

    1. rm(list = ls())
    2. library(WGCNA)
    3. load(file = 'input.Rdata')
    4. load(file = "step2_beta_value.Rdata")
    5. load(file = "step3_genes_modules.Rdata")
    6. load(file = "step4_design.Rdata")
    7. load(file="step4_datTraits.Rdata")
    8. load(file="step5_GOananlysis.Rdata")
    9. # 主要是可视化 TOM矩阵,WGCNA的标准配图
    10. # 然后可视化不同 模块 的相关性 热图
    11. # 不同模块的层次聚类图
    12. # 还有模块诊断,主要是 intramodular connectivity
    13. if(T){
    14.   #geneTree = net$dendrograms[[1]]
    15.   TOM=TOMsimilarityFromExpr(datExpr,power=20)
    16.   dissTOM=1-TOM
    17.   #plotTOM = dissTOM^7
    18.   #diag(plotTOM)=NA
    19.   #TOMplot(plotTOM,geneTree,moduleColors,main="Network heapmap plot of all genes")
    20.   ### 我这里只取了1000个基因哈,我试了一下全部基因,结果跑了半个小时没跑完,被我强行退出!
    21.   nSelect =1000
    22.   set.seed(20)
    23.   select=sample(nGenes,size = nSelect)
    24.   selectTOM = dissTOM[select,select]
    25.   selectTree = hclust(as.dist(selectTOM),method = "average")
    26.   selectColors = moduleColors[select]
    27.   plotDiss=selectTOM^7
    28.   diag(plotDiss)=NA
    29.   png("figures/step6_select_Network-heatmap.png",width = 800,height=600)
    30.   TOMplot(plotDiss,selectTree,selectColors,main="Network heapmap of selected gene")
    31.   dev.off()
    32. }

    如下:

    5.6 提取指定模块的基因并做热图

    1. if(T){
    2.   module="turquoise"
    3.   which.module=module
    4.   dat=datExpr[,moduleColors==which.module]
    5.   library(pheatmap)
    6.   pheatmap(dat,show_colnames = F,show_rownames = F)
    7.   n=scale(t(dat+1)) # 'scale'可以对log-ratio数值进行归一化
    8.   n[n>2]=2 
    9.   n[n< -2]= -2
    10.   n[1:4,1:4]
    11.   pheatmap(n,show_colnames =F,show_rownames = F)
    12.   group_list=datTraits$group
    13.   ac=data.frame(g=group_list)
    14.   rownames(ac)=colnames(n)
    15.   png("figures/step6-moduleGene-heatmap.png",width = 800,height = 600)
    16.   pheatmap(n,show_colnames =F,show_rownames = F,annotation_col =ac )
    17.   dev.off()
    18. }

    都挺好的。

    点评:这个热图有问题,具体代码是  n=scale(t(dat+1)) 里面少了一个转置!

    5.7 性状与模块的关系

    1. if(T){
    2.   ## 连续性的变量,如体重等才好和模块进行比较。
    3.   MEs=moduleEigengenes(datExpr,moduleColors)$eigengenes
    4.   MET = orderMEs(cbind(MEs,datTraits$groupNo))
    5.   par(cex = 0.9)
    6.   png("figures/step6-Eigengene-dendrogram.png",width = 800,height = 600)
    7.   plotEigengeneNetworks(MET, "", marDendro = c(0,4,1,2), marHeatmap = c(3,4,1,2), cex.lab = 0.8, xLabelsAngle
    8.                         = 90)
    9.   dev.off()
    10. }

    如图:

    6. 模块导出

    感兴趣的模块导出到cytoscape,VisANT等软件进一步进行可视化分析。

    1. #######gene export for VisANT or cytoscape
    2. if(T){
    3.   module="turquoise"
    4.   probes = colnames(datExpr)
    5.   inModule = (moduleColors==module)
    6.   modProbes=probes[inModule]
    7.   head(modProbes)
    8.   modTOM = TOM[inModule,inModule]
    9.   dimnames(modTOM)=list(modProbes,modProbes)
    10.   ### 这里只选了top100的基因
    11.   nTop=100
    12.   IMConn = softConnectivity(datExpr[,modProbes])
    13.   top=(rank(-IMConn)<=nTop)
    14.   filterTOM=modTOM[top,top]
    15.   # for visANT
    16.   vis = exportNetworkToVisANT(filterTOM,file = paste("figures/visANTinput-",module,".txt",sep = ""),
    17.                               weighted = T,threshold = 0)
    18.   # for cytoscape
    19.   cyt = exportNetworkToCytoscape(filterTOM,
    20.                                  edgeFile = paste("figures/CytoscapeInput-edges-", paste(module, collapse="-"), ".txt", sep=""),
    21.                                  nodeFile = paste("figures/CytoscapeInput-nodes-", paste(module, collapse="-"), ".txt", sep=""),
    22.                                  weighted = TRUE,
    23.                                  threshold = 0.02,
    24.                                  nodeNames = modProbes[top], 
    25.                                  nodeAttr = moduleColors[inModule][top])
    26. }

    总结

           至此,复现结束。如果你仔细的看到了这里,说明你是想学WGCNA的了。回到课题本身,是否对小胶质细胞的认识更近了一步?提个小小的科学问题:在PD中,是否有一个胶质细胞亚群可对MPP+诱导的黑质神经细胞死亡有抵抗和保护作用?哈哈,别说我是搞肿瘤的了。。。

           这些内容,换个思路应该够一个硕士毕业了。。。

    1. rm(list = ls())
    2. dev.off()
    3. library(WGCNA)
    4. # 偷懒,读取作者给出的附件的表达矩阵
    5. getwd()
    6. file="G:/papers_for_ARDS/r_scripts_for_ARDS_From_zhongda/lncRNA_mRNA_cicleRNA/microglial cells/EMBJ-36-3292-s002/embj201696056-sup-0003-DatasetEV1"
    7. dir.create(file)
    8. setwd(file)
    9. getwd()
    10. ??read.csv
    11. norm.counts <- openxlsx::read.xlsx("Dataset_EV1.xlsx",
    12. sheet = 2) ##original counts
    13. head(norm.counts)
    14. rownames(norm.counts)<-norm.counts[,1]
    15. norm.counts <- norm.counts[,2:18]
    16. head(norm.counts)
    17. save(norm.counts,file = "norm.counts.Rdata")
    18. load("norm.counts.Rdata")
    19. ## 处理表型信息,就是老鼠的分组信息
    20. a <- colnames(norm.counts)
    21. library(stringr)
    22. str_split(a,"[,]",simplify = T)
    23. strsplit("UK, USA, Germany", ",(?=[^,]+$)", perl=TRUE)
    24. str_split(a, ",(?=[^,]+$)",simplify = T)
    25. #以最后一个逗号为分割符号 切割字符串
    26. str_tmp=as.data.frame(str_split(a, ",(?=[^,]+$)",simplify = T))
    27. rownames(str_tmp) <- colnames(norm.counts)
    28. colnames(str_tmp) <- c("group","sampleRep")
    29. str_tmp
    30. datTraits <- str_tmp
    31. datTraits$groupNo <- c(rep(1,3),rep(2,4),rep(3,4),rep(4,3),rep(5,3))
    32. datTraits
    33. ###数据初步处理完成
    34. ## 筛选中位绝对偏差前75%的基因,取MAD大于0.3
    35. ## 筛选后会降低运算量,也会失去部分信息
    36. ## 也可不做筛选,使MAD大于0即可
    37. head(norm.counts)
    38. norm.counts <- log2(norm.counts) ##注意我在这里进行了log2,因为我发现如果不log的话,出现了个很有意思的现象,请您往下看
    39. m.mad <- apply(norm.counts,1,mad)
    40. dataExprMad <- norm.counts[which(m.mad > max(quantile(m.mad, probs=seq(0, 1, 0.25))[2],0.3)),] #25% = 0.22
    41. datExpr0 <- as.data.frame(t(dataExprMad))
    42. dim(datExpr0)
    43. head(datExpr0)[1:10,1:10]
    44. ##最终取到8222个基因。
    45. ###########start handling the data
    46. ##看看有没有为空的值,需要剔除。这里下载的都是作者处理好的,基本没问题。
    47. gsg <- goodSamplesGenes(datExpr0,verbose = 3)
    48. gsg$allOK
    49. if (!gsg$allOK){
    50. # Optionally, print the gene and sample names that were removed:
    51. if (sum(!gsg$goodGenes)>0)
    52. printFlush(paste("Removing genes:", paste(names(datExpr0)[!gsg$goodGenes],
    53. collapse = ", ")));
    54. if (sum(!gsg$goodSamples)>0)
    55. printFlush(paste("Removing samples:",
    56. paste(rownames(datExpr0)[!gsg$goodSamples], collapse = ", ")));
    57. # Remove the offending genes and samples from the data:
    58. datExpr0 = datExpr0[gsg$goodSamples, gsg$goodGenes]
    59. }
    60. gsg <- goodSamplesGenes(datExpr0,verbose = 3)
    61. gsg$allOK
    62. ###画个树看看样本有没有离群值!!!
    63. if(T){
    64. # Plot a line to show the cut
    65. sampleTree <- hclust(dist(datExpr0),method = "average")
    66. par(cex=.6)
    67. par(mar=c(0,4,2,0))
    68. plot(sampleTree, main = "Sample clustering to detect outliers", sub = "",
    69. xlab = "",cex.lab = 1.5, cex.axis =1.5, cex.main=2
    70. )
    71. }
    72. ##然后保存数据
    73. dim(datExpr0) ##178222
    74. datExpr <- datExpr0
    75. nGenes <- ncol(datExpr)
    76. nSamples <- nrow(datExpr)
    77. save(nGenes,nSamples,datExpr,datTraits,file="input.Rdata")
    78. rm(list = ls())
    79. library(WGCNA)
    80. load(file = "input.Rdata")
    81. dim(datExpr)
    82. head(datTraits)
    83. #################################################
    84. if(T){
    85. powers = c(c(1:10), seq(from = 12, to=30, by=2))
    86. # Call the network topology analysis function
    87. sft = pickSoftThreshold(datExpr, powerVector = powers, verbose = 5)
    88. dev.off()
    89. getwd()
    90. dir.create("./figures")
    91. png("figures/step2-beta-value.png",width = 800,height = 600)
    92. # Plot the results:
    93. ##sizeGrWindow(9, 5)
    94. par(mfrow = c(1,2));
    95. cex1 = 0.9;
    96. # Scale-free topology fit index as a function of the soft-thresholding power
    97. plot(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
    98. xlab="Soft Threshold (power)",ylab="Scale Free Topology Model Fit,signed R^2",type="n",
    99. main = paste("Scale independence"));
    100. text(sft$fitIndices[,1], -sign(sft$fitIndices[,3])*sft$fitIndices[,2],
    101. labels=powers,cex=cex1,col="red");
    102. # this line corresponds to using an R^2 cut-off of h
    103. abline(h=0.9,col="red")
    104. # Mean connectivity as a function of the soft-thresholding power
    105. plot(sft$fitIndices[,1], sft$fitIndices[,5],
    106. xlab="Soft Threshold (power)",ylab="Mean Connectivity", type="n",
    107. main = paste("Mean connectivity"))
    108. text(sft$fitIndices[,1], sft$fitIndices[,5], labels=powers, cex=cex1,col="red")
    109. dev.off()
    110. }
    111. sft$powerEstimate ## beta=22 SCI文章里面用了20
    112. save(sft,file = "step2_beta_value.Rdata")
    113. rm(list = ls())
    114. library(WGCNA)
    115. load(file = "input.Rdata")
    116. load(file = "step2_beta_value.Rdata")
    117. enableWGCNAThreads()
    118. if(T){
    119. net = blockwiseModules(
    120. datExpr,
    121. power = sft$powerEstimate,
    122. maxBlockSize = nGenes,
    123. TOMType = "unsigned", minModuleSize = 30,
    124. reassignThreshold = 0, mergeCutHeight = 0.28, ## 注意这个0.28
    125. numericLabels = TRUE, pamRespectsDendro = FALSE,
    126. saveTOMs = F,
    127. verbose = 3
    128. )
    129. table(net$colors)
    130. }
    131. ##模块可视化,画那个传说中的树
    132. if(T){
    133. # Convert labels to colors for plotting
    134. moduleColors=labels2colors(net$colors)
    135. table(moduleColors)
    136. # Plot the dendrogram and the module colors underneath
    137. png("figures/step3-genes-modules.png",width = 800,height = 600)
    138. plotDendroAndColors(net$dendrograms[[1]], moduleColors[net$blockGenes[[1]]],
    139. "Module colors",
    140. dendroLabels = FALSE, hang = 0.03,
    141. addGuide = TRUE, guideHang = 0.05)
    142. dev.off()
    143. }
    144. save(net,moduleColors,file = "step3_genes_modules.Rdata")
    145. rm(list = ls())
    146. library(WGCNA)
    147. load(file = "input.Rdata")
    148. load(file = "step2_beta_value.Rdata")
    149. load(file = "step3_genes_modules.Rdata")
    150. if(T){
    151. nGenes = ncol(datExpr)
    152. nSamples = nrow(datExpr)
    153. datTraits
    154. design <- model.matrix(~0+datTraits$group)
    155. colnames(design)= levels(as.factor(datTraits$group)) ## get the group
    156. design
    157. MES0 <- moduleEigengenes(datExpr,moduleColors)$eigengenes
    158. head(MES0)
    159. MEs = orderMEs(MES0)
    160. head(MEs)
    161. head(design)
    162. moduleTraitCor <- cor(MEs,design,use = "p")
    163. head(moduleTraitCor)
    164. moduleTraitPvalue <- corPvalueStudent(moduleTraitCor,nSamples)
    165. textMatrix = paste(signif(moduleTraitCor,2),"\n(",
    166. signif(moduleTraitPvalue,1),")",sep = "")
    167. dim(textMatrix)=dim(moduleTraitCor)
    168. textMatrix
    169. png("figures/step4-Module-trait-relationship.png",width = 800,height = 1200,res = 120)
    170. par(mar=c(6, 8.5, 3, 3))
    171. labeledHeatmap(Matrix = moduleTraitCor,
    172. xLabels = colnames(design),
    173. yLabels = names(MEs),
    174. ySymbols = names(MEs),
    175. colorLabels = FALSE,
    176. colors = blueWhiteRed(50),
    177. textMatrix = textMatrix,
    178. setStdMargins = FALSE,
    179. cex.text = 0.5,
    180. zlim = c(-1,1),
    181. main = paste("Module-trait relationships"))
    182. dev.off()
    183. save(design,file = "step4_design.Rdata")
    184. }
    185. if(T){
    186. mes_group <- merge(MEs,datTraits,by="row.names") # 小技巧,可以通过rowname进行merge
    187. ##写了个画图的function
    188. library(gplots)
    189. library(ggplot2)
    190. library(ggpubr)
    191. library(grid)
    192. library(gridExtra)
    193. draw_ggboxplot <- function(data,gene="P53",group="group"){
    194. #print(gene)
    195. ggboxplot(data,x=group, y=gene,
    196. ylab = sprintf("Expression of %s",gene),
    197. xlab = group,
    198. fill = group,
    199. palette = "jco",
    200. #add="jitter",
    201. legend = "") +stat_compare_means()
    202. }
    203. ###开始批量画boxplot
    204. colorNames = names(MEs)
    205. png("figures/step4-expression-group.png",width = 800,height=2000,res = 120)
    206. #par(mfrow=c(ceiling(length(colorNames)/2),2))
    207. p <- lapply(colorNames,function(x) {
    208. draw_ggboxplot(mes_group,gene= x,group="group")
    209. })
    210. do.call(grid.arrange,c(p,ncol=2))
    211. dev.off()
    212. }
    213. if(T){
    214. modNames = substring(names(MEs), 3)
    215. modNames
    216. head(MEs)
    217. head(datExpr)[1:6:1:9]
    218. geneModuleMembership = as.data.frame(cor(datExpr, MEs, use = "p"))
    219. ## 算出每个模块跟基因的皮尔森相关系数矩阵
    220. ## MEs是每个模块在每个样本里面的值
    221. ## datExpr是每个基因在每个样本的表达量
    222. MMPvalue = as.data.frame(corPvalueStudent(as.matrix(geneModuleMembership), nSamples))
    223. names(geneModuleMembership) = paste("MM", modNames, sep="")
    224. names(MMPvalue) = paste("p.MM", modNames, sep="")
    225. head(MMPvalue)
    226. geneTraitSignificance <- as.data.frame(cor(datExpr,datTraits$groupNo,use = "p"))
    227. head(geneTraitSignificance)
    228. GSPvalue <- as.data.frame(corPvalueStudent(as.matrix(geneTraitSignificance),nSamples))
    229. head(GSPvalue)
    230. names(geneTraitSignificance)<- paste("GS.",names(datTraits$group),sep = "")
    231. names(GSPvalue)<-paste("GS.",names(datTraits$group),sep = "")
    232. head(GSPvalue)
    233. #selectModule<-c("blue","green","purple","grey") ##可以选择自己喜欢的模块
    234. selectModule <- modNames ## 也可以批量作图
    235. png("figures/step4-Module-trait-significance.png",width = 800,height=2000,res = 120)
    236. par(mfrow=c(ceiling(length(selectModule)/2),2)) #批量作图开始
    237. for(module in selectModule){
    238. column <- match(module,selectModule)
    239. print(module)
    240. moduleGenes <- moduleColors==module
    241. verboseScatterplot(abs(geneModuleMembership[moduleGenes, column]),
    242. abs(geneTraitSignificance[moduleGenes, 1]),
    243. xlab = paste("Module Membership in", module, "module"),
    244. ylab = paste("Gene significance for", module, "module"),
    245. main = paste("Module membership vs. gene significance\n"),
    246. cex.main = 1.2, cex.lab = 1.2, cex.axis = 1.2, col = module)
    247. }
    248. dev.off()
    249. }

  • 相关阅读:
    (原创)[C#] GDI+ 之鼠标交互:原理、示例、一步步深入、性能优化
    Greenplum外表gpfdist加载数据
    6.6 - Windows网络相关命令
    最长回文串-力扣409-C++
    基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的零售柜商品检测软件(Python+PySide6界面+训练代码)
    【Java】继承练习
    Windows上运行Redis
    vue如何使用深度选择器?
    想做扫码看图效果,你需要学会这一招
    【Flutter】使用Android Studio 创建第一个flutter应用。
  • 原文地址:https://blog.csdn.net/qq_52813185/article/details/127681071