查看原文
其他

拖后腿学徒居然也完成作业,理解RNA-seq数据分析结果

生信技能树 生信技能树 2022-08-10

前面我出了一个学徒作业,下载表达矩阵后绘制PCA图及热图,然后理解作者给出的RPM和raw_counts的差异,详见:理解RNA-seq表达矩阵的两个形式 很意外,12月学徒肖一僧居然吭哧吭哧的完成了,吓我一跳!让我们看看他的表演

以下是正文

收到大佬的作业,第一次投稿。大佬的题目如下:通过一篇science文章,理解两种RNA-seq表达矩阵在数据分析的时候是否相同(大佬的意思是通过PCA和heatmap来看一下)。


稍微介绍 一下背景

Counts值

对给定的基因组参考区域,计算比对上的read数,又称为raw count(RC),也就我通常说的相对原始的数据,是没进行任何标准化操作的数据。

计数结果的差异的影响因素:落在参考区域上下限的read是否需要被统计,按照什么样的标准进行统计。

RPM (Reads per million mapped reads)

 

RPM方法:10^6标准化了测序深度的影响,以前说这个没有考虑转录本的长度的影响。表示RPM适合于产生的read读数不受基因长度影响的测序方法,比如miRNA-seq测序,miRNA的长度一般在20-24个碱基之间。但是现在的观点(Jimmy大佬说)认为,我们通常做差异表达,同于对比系统下转录本长度是一致(例如一个患者的癌跟癌旁),所以我们只要需要考虑测序深度的影响,所以这个RPM是比较好的一种数据标准化方式。


可能优于RPKM/FPKM (Reads/Fragments per kilo base per million mapped reads)。这个网页也说明了这个问题:https://www.jianshu.com/p/35e861b76486

下面给给出我的答案及代码

一,读取数据,并做一下常规的转换
###一些常规的设置
rm(list = ls())#清空环境变量
options(stringsAsFactors = F)##字符不作为因子读入
###读取数据。
##rawcounts##
a <- read.table('GSE103788_raw_counts_genes.tsv.gz',header = T,row.names = 1)
a[1:4,1:4]##大概看一下数据格式。
###                         PH_WT_tumors_r1 PH_WT_tumors_r2
ENSMUSG00000000001_Gnai3            1827            2772
ENSMUSG00000000028_Cdc45              44              88
ENSMUSG00000000031_H19                19             500
ENSMUSG00000000037_Scml2               5              10
                         PH_WT_tumors_r3 PH_WT_notreat_r1
ENSMUSG00000000001_Gnai3            2149             3264
ENSMUSG00000000028_Cdc45              72               28
ENSMUSG00000000031_H19                39                1
ENSMUSG00000000037_Scml2              11                3

##RPM##
b <- read.table('GSE103788_filtered_RPM_genes.tsv.gz',header = T,row.names = 1)
b[1:4,1:4]
##                         PH_WT_tumors_r1 PH_WT_tumors_r2
ENSMUSG00000000001_Gnai3     111.4598680     149.6572460
ENSMUSG00000000028_Cdc45       2.6843099       4.7510237
ENSMUSG00000000031_H19         1.1591338      26.9944527
ENSMUSG00000000037_Scml2       0.3050352       0.5398891
                         PH_WT_tumors_r3 PH_WT_notreat_r1
ENSMUSG00000000001_Gnai3     120.3417347     183.67178123
ENSMUSG00000000028_Cdc45       4.0319241       1.57561577
ENSMUSG00000000031_H19         2.1839589       0.05627199
ENSMUSG00000000037_Scml2       0.6159884       0.16881598
##查看数据是否需要做log转换。
qx <- as.numeric(quantile(a, c(0., 0.25, 0.5, 0.75, 0.99, 1.0), na.rm=T))
LogC <- (qx[5] >
 100) ||
  (qx[6]-qx[1] > 50 && qx[2] > 0) ||
  (qx[2] > 0 && qx[2] < 1 && qx[4] > 1 && qx[4] < 2)
LogC
##[1] TRUE
##########boxplot可视化数据检查数据是否需要log等转换
boxplot(a,las=2,cex.axis=0.6,main='data check')
###去除低碱基质量的基因。
a=a[apply(a,1, function(x) sum(x>1) > 6),]

ex<- log2(a+1)##转换
boxplot(ex,las=2,cex.axis=0.6,main='data check')

下图是转换前后的图片。


同上方法,处理一下RPM的数据。
##########boxplot可视化数据检查
boxplot(b,las=2,cex.axis=0.6,main='data check')
###转换
ex1<- log2(b+1)
boxplot(ex1,las=2,cex.axis=0.6,main='
data check')

二,提取数据
##提取数据。因为之前讲过,我们只看肿瘤周围的肝细胞跟正常肝周细胞对比。所以在此我们提取我们的目的数据。##
PHex <- ex[,1:6]
PHex[1:4,1:6]##查看一下数据。(rawcounts数据)
##                         PH_WT_tumors_r1 PH_WT_tumors_r2
ENSMUSG00000000001_Gnai3       10.836050       11.437232
ENSMUSG00000000028_Cdc45        5.491853        6.475733
ENSMUSG00000000031_H19          4.321928        8.968667
ENSMUSG00000000037_Scml2        2.584963        3.459432
                         PH_WT_tumors_r3 PH_WT_notreat_r1
ENSMUSG00000000001_Gnai3       11.070121        11.672867
ENSMUSG00000000028_Cdc45        6.189825         4.857981
ENSMUSG00000000031_H19          5.321928         1.000000
ENSMUSG00000000037_Scml2        3.584963         2.000000
                         PH_WT_notreat_r2 PH_WT_notreat_r3
ENSMUSG00000000001_Gnai3        11.712957        11.007027
ENSMUSG00000000028_Cdc45         6.321928         3.584963
ENSMUSG00000000031_H19           0.000000         2.000000
ENSMUSG00000000037_Scml2         3.169925         0.000000
PHex1<- ex1[,1:6]
PHex1[1:4,1:6]##查看一下数据。(RPM数据)
##                         PH_WT_tumors_r1 PH_WT_tumors_r2
ENSMUSG00000000001_Gnai3       6.8132664       7.2351263
ENSMUSG00000000028_Cdc45       1.8813944       2.5238188
ENSMUSG00000000031_H19         1.1104527       4.8070691
ENSMUSG00000000037_Scml2       0.3840887       0.6228264
                         PH_WT_tumors_r3 PH_WT_notreat_r1
ENSMUSG00000000001_Gnai3       6.9229320       7.52881962
ENSMUSG00000000028_Cdc45       2.3311102       1.36491739
ENSMUSG00000000031_H19         1.6708217       0.07898138
ENSMUSG00000000037_Scml2       0.6924168       0.22504780
                         PH_WT_notreat_r2 PH_WT_notreat_r3
ENSMUSG00000000001_Gnai3        7.6446714        6.9971839
ENSMUSG00000000028_Cdc45        2.5076949        0.7465790
ENSMUSG00000000031_H19          0.0000000        0.2447131
ENSMUSG00000000037_Scml2        0.5603664        0.0000000
三,画PCA图
library(stringr)
###分组
group_list1=str_split(colnames(PHex),'_',simplify = T)[,3]
group_list2=str_split(colnames(Lex),'_',simplify = T)[,3]
> group_list1
[1"tumors"  "tumors"  "tumors"  "notreat" "notreat" "notreat"
####PCA看分组情况
library("FactoMineR")
library("factoextra")
####a data frame with n rows (individuals) 
####and p columns (numeric variables)
df.pca <- PCA(t(PHex), graph = FALSE)
fviz_pca_ind(df.pca,
             geom.ind = "point",
             col.ind = group_list1, 
             addEllipses = TRUE
             legend.title = "Groups"
)
df.pca1 <- PCA(t(PHex1), graph = FALSE)
fviz_pca_ind(df.pca1,
             geom.ind = "point",
             col.ind = group_list2, 
             addEllipses = TRUE
             legend.title = "Groups"
)

我觉得从PCA分群来看,这个两个数据格式,应该没有太多的区别,都是很好的区分这个两组。

四,画热图
##画热图。
PHex<-na.omit(PHex)##去一下个别缺失值。
table(is.na.data.frame(PHex))##检测一下缺失值是否去干净,因为热图十不可以有缺失值的。
cg=names(tail(sort(apply(PHex,1,sd)),200))##选两百个去做热图。
PHex <- PHex[cg,]
PHex=t(scale(t(PHex)))
#####查看scale处理后数据的范围
fivenum(PHex)
####目的是避免出现极大极小值影响可视化的效果
###2,-2
PHex[PHex>1.2]=1.2
PHex[PHex< -1.2] = -1.2
library(pheatmap)
pheatmap(PHex)##这个画的比较丑,下面调整一下颜色,加入分组之后会漂亮许多。
####调整下颜色,使正负值颜色的对比会更加鲜明
require(RColorBrewer)
bk = c(seq(-1.2,1.2, length=100))
annotation_col = data.frame(Group = rep(c("tumors""notreat"), c(3,3)))
rownames(annotation_col)<-colnames(PHex)
####annotation_col和annotation_row的格式需为数据框
####breaks参数用于值匹配颜色
####看下,color和breaks的对应,进行理解
pheatmap(PHex,
         breaks=bk,
         show_rownames = F,
         annotation_col = annotation_col,
         color = colorRampPalette(c("navy""white""firebrick3"))(100))
####可以调整的内容有是否聚类、是否分组、是否显示行和列的内容等
save(PHex,PHex1,group_list1,group_list2,file = 'ex.Rdata')
##同上换成PHex1再画个图##

热图聚类都可以聚的很好,两个数据很相似。但是具体里面差异基因是不是一致的呢?我觉得通过这两个图只能看一个大概,啥也说明不了。好吧接下来试着复现一下文章中的go功能注释的图把。

五,差异分析(DESeq2+rawcounts)
load('ex.Rdata')
exprSet<- read.table('GSE103788_raw_counts_genes.tsv.gz',header = T,row.names = 1)
exprSet=exprSet[apply(exprSet,1function(x) sum(x>1) > 6),]
exprSet <- exprSet[,1:6]
group_list <- factor(group_list1)
### Firstly run DEseq2 
###
### ---------------
class(exprSet)
suppressMessages(library(DESeq2))  
(colData <- data.frame(row.names=colnames(exprSet), 
                       group_list=group_list) )
dds <- DESeqDataSetFromMatrix(countData = exprSet,
                              colData = colData,
                              design = ~ group_list)
dds <- DESeq(dds)
res <- results(dds, 
               contrast=c("group_list",'tumors','notreat'))
resOrdered <- res[order(res$padj),]
head(resOrdered)
DEG =as.data.frame(resOrdered)
DEG = na.omit(DEG)
head(DEG)

#####                      baseMean log2FoldChange     lfcSE
ENSMUSG00000026678_Rgs5    975.6113       3.152064 0.2122172
ENSMUSG00000026473_Glul   7295.5197       3.265248 0.2312006
ENSMUSG00000031375_Bgn    2390.6760       3.661976 0.2659914
ENSMUSG00000021268_Meg3    306.8778       6.370573 0.4675770
ENSMUSG00000002900_Lamb1   242.4983       3.679213 0.2704702
ENSMUSG00000069662_Marcks  526.7389       2.888859 0.2137369
                              stat       pvalue         padj
ENSMUSG00000026678_Rgs5   14.85301 6.651063e-50 1.003313e-45
ENSMUSG00000026473_Glul   14.12301 2.740446e-45 2.066981e-41
ENSMUSG00000031375_Bgn    13.76727 4.010678e-43 2.016702e-39
ENSMUSG00000021268_Meg3   13.62465 2.857755e-42 1.077731e-38
ENSMUSG00000002900_Lamb1  13.60303 3.841994e-42 1.159130e-38
ENSMUSG00000069662_Marcks 13.51596 1.259102e-41 3.165593e-38
五,GO注释(这里主要用一下Y叔的优秀的通路分析包,图又漂亮,有方便使用)。

geneList准备,Y叔的注释包(clusterProfiler)只要这个做好后,后面代码基本上不用改了。直接运行了。所以这个很重要。

rm(list = ls())
options(stringsAsFactors = F)
library(ggplot2)
library(clusterProfiler)
library(stringr)
library(org.Mm.eg.db)
keytypes(org.Mm.eg.db)
load('DEG.Rdata')
b <- rownames(DEG)
b=str_split(rownames(DEG),'_',simplify = T)[,1]
rownames(DEG) <- b
gene<- bitr(b, fromType = "ENSEMBL"#fromType是指你的数据ID类型是属于哪一类的
                toType = c('ENTREZID'), #toType是指你要转换成哪种ID类型,可以写多种,也可以只写一种
                OrgDb = org.Mm.eg.db)#Orgdb是指对应的注释包是哪个
DEG$ENSEMBL<- rownames(DEG)
DEG<- merge(gene,DEG)

## assume that 1st column is ID
## 2nd column is fold change

## feature 1: numeric vector(输入差异倍数列)
geneList <- DEG[,4]

## feature 2: named vector
names(geneList) <- as.character(DEG[,2])##(输入ID列)

## feature 3: decreasing order
geneList <- sort(geneList, decreasing = TRUE)
save(geneList,file='geneList.Rdata')
head(geneList)
>head(geneList)
   216643     53973     57430    117586     12323    337924 
13.402835 11.655016 11.097527 10.804276  9.923125  9.889644

go注释

rm(list = ls())
options(stringsAsFactors = F)
library(clusterProfiler)
library(org.Mm.eg.db)
load('geneList.Rdata')

##GO classification
gene <- names(geneList)[abs(geneList) > 2]#筛选差异基因大于2的列表
gene.df <- bitr(gene, fromType = "ENTREZID",
                toType = c("ENSEMBL""SYMBOL"),##得到ENSEMBLID与基因名
                OrgDb = org.Mm.eg.db)
head(gene.df)

##BP##
ego2 <- enrichGO(gene         = gene.df$ENSEMBL,
                 OrgDb         = org.Mm.eg.db,
                 keyType       = 'ENSEMBL',
                 ont           = "BP",
                 pAdjustMethod = "BH",
                 pvalueCutoff  = 0.01,
                 qvalueCutoff  = 0.05)
ego2 <- setReadable(ego2, OrgDb = org.Mm.eg.db)
##去掉一些重复的通路。
lineage1_ego <- simplify(ego2, 
                         cutoff=0.5
                         by="p.adjust"
                         select_fun=min)
##可视化
barplot(lineage1_ego,showCategory=25)

BP注释总体上跟文章中的通路还是类似的。毕竟如果不知道代码,很难一模一样复现文章的图的。只要趋势差不多就差不多了。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存