关于RNAseq
Nature重磅综述 |关于RNA-seq,你想知道的都在这
准备工作
先在服务器安装conda。安装好通过conda进一步安装所需要的软件。
通过conda安装fastqc(质控), hisat2(比对), multiqc(质控合并), samtools(sam文件转bam文件), subread(featureCounts集合在其中)。建议先创建一个虚拟环境。
SRA toolkit软件(用于下载和处理NCBI的数据)下载,在官网下载自己合适的版本(使用conda安装时失败了)。
参考代码:
conda create -n RNAseq #新建一个名为RNAseq的conda环境
conda activate RNAseq #激活并进入新建的RNAseq环境
conda install fastqc hisat2 samtools subread multiqc trimmomatic #安装所需要的软件
数据准备
数据下载
在GEO数据库下载PRJNA639275数据集,这个数据集共有34个样本(16个新冠患者,17个正常样本),每个样本测序两次。
prefetch SRRXXXXXX -O output # output更换为路径
prefetch -O output --option-file SRR_Acc_list.txt #批量下载
数据处理
sra转fastq格式
for name in SRR120078*; do fastq-dump
--split-files #双端测序时需要加这个参数
--gzip #加上-gzip可以使fq文件压缩,节约空间
-O /path to save/ # -O 指定输出位置
/path to input/${name}/*sra; done #遍历处理所有下载的数据
如果是自己的测序文件则需要对比md5码来检查数据完整性
md5sum *gz > md5.txt && md5sum -c md5.txt
# *gz 任意以gz结尾的文件
# > 运行结果保存至
# && 连接符,前一命令完成继续执行下一命令
质量评估与质控
multiqc是合并报告的一个Python包,报告解读
操作说明见官方用户手册
multiqc只能识别 *report.html
方法一:使用fastp质控
fastp的安装
fastp的数据质控原理
个人感觉fastp比trimmomatic要方便
单端:fastp -i raw.fq -o clean.fq
双端:fastp -i raw_1.fq -I raw_2.fq -o clean_1.fq -O clean_2.fq
参数:
-l
36 #过滤后的最短序列长度,默认为15
-j
xxx.json 过滤报告文件
-h
xxx.report.html 过滤报告文件
单端测序
for name in *fq;do fastp \
-i ./${name}/*gz \
-o./fastp_clean/clean_${name}.gz \
-l 36 \
-h ./fastp_reports/${name}.html;
done
multiqc ./fastp_reports/ -o ./multiqc_reports/
双端测序
fastp \
-i R1_fastq.gz \
-I R2_fastq.gz \
-o R1_output \
-O R2_output\
-l 36 \
-j jsonfile \
-h htmlfile
方法二:使用fastqc质量评估和trimmomatic质控
fastqc基本介绍
fastqc -o fastqc_output ./rawdata/*gz
multiqc fastqc_output -o output
# 对所有gz结尾文件进行质控并对当前目录下所有质控报告进行合并
trimmomatic
参考用法说明
trimmomatic SE -phred33 \
input.fq.gz output_fq.gz \
ILLUMINACLIP:TruSeq3-SE.fa:2:30:10 \
LEADING:3 \
TRAILING:3 \
MINLEN:36 #单端
trimmomatic PE -phred33 \
input_forward.fq.gz input_reverse.fq.gz \
output_forward_paired.fq.gz output_forward_unpaired.fq.gz \
output_reverse_paired.fq.gz output_reverse_unpaired.fq.gz \
ILLUMINACLIP:TruSeq3-PE.fa:2:30:10 \
LEADING:3 \
TRAILING:3 \
MINLEN:36 #双端
hisat2比对
准备工作
在官网直接下载对应的基因组索引文件然后解压即可生成8个索引文件。
wget https://genome-idx.s3.amazonaws.com/hisat/grch38_genome.tar.gz
tar -zxvf grch38_genome.tar.gz
#grch38/
#grch38/genome.5.ht2
#grch38/genome.2.ht2
#grch38/make_grch38.sh
#grch38/genome.3.ht2
#grch38/genome.4.ht2
#grch38/genome.7.ht2
#grch38/genome.1.ht2
#grch38/genome.6.ht2
#grch38/genome.8.ht2
或者根据不同需求在genecode下载基因组fa文件和注释GTF文件,然后在通过hisat2-build去建立索引。
比对
hisat2 -p 8 \
-x ref/grch38/genome \
-1 sample_1.fq.gz -2 sample_2.fq.gz \
-S sample.sam \
--summary-file sample.hisat2.summary
-p
: 线程数
-x
: 基因组索引前缀。所下的基因组索引为多个文件,索引前缀到genome为止。
-1/-2
: fastq输入文件。当输入为单端测序时使用-U 指定输入。
单端或双端的输入都可使用逗号分隔输入多个样本,或使用多次-1 -2 / -U 指定多个输入。
e.g.:-U
sample1.fq.gz,sample2.fq.gz -U sample3.fq.gz
-S
: 输出sam文件路径。
--summary-file
: 生成summary文件。
sam转bam
使用samtools将sam文件转换为bam文件,bam文件为二进制文件,能大大压缩体积
samtools sort -@ 8 -o sample.bam sample.sam
# sort:排序
# -@:线程数
# -o:输出bam文件
计数
试用featureCounts进行计数,这一步需要基因组注释文件,在genecode下载GTF文件即可。
featureCounts -p -T 8 -a ref/annotation.gtf.gz -o featurecounts.out \
[sample1.bam sample2.bam ...] *.bam
# -p: 此参数双端测序时使用
# -T: 线程数
# -a: 基因组注释文件
# -o: 输出文件
# 最后为bam文件,可指定多个输入
DESeq2差异表达分析
Ensembl ID和gene symbol相互转换
下载转换参照表
选择对应物种,左侧Attributes只选择Gene stable ID 和 Gene name,然后点击左上角的resuls,最后点击GO导出文件。
根据参考文件在计数文件中添加symbol name。
或用R包实现。
R语言实现ID转换
BiocManager::install("org.Mm.eg.db") #Mm:小鼠,Hs:人
library('org.Mm.eg.db')
matrix <- read.csv("./featurecounts.txt",sep="\t",stringsAsFactors = F,header = F)
colnames(matrix) <- matrix[2,]
matrix <- matrix[-1:-2,]
rownames(matrix) <- 1:nrow(matrix)
for (i in 1:nrow(matrix)){
matrix[i,"Geneid"] <- strsplit(matrix[i,"Geneid"], split = "\\.")[[1]][1]
}
mycounts <- matrix[,-2:-6]
colnames(mycounts)[1] <- "ensembl_id" #列名需要更改
g2s=toTable(org.Mm.egSYMBOL)
g2e=toTable(org.Mm.egENSEMBL)
b=merge(mycounts,g2e,by="ensembl_id",all.x=T)
d=merge(b,g2s,by="gene_id",all.x=T)
d=d[order(d$ensembl_id),]
table(d$symbol)[table(d$symbol)>1]
d=d[!duplicated(d$symbol),] #去重
d=d[match(mycounts$ensembl_id,d$ensembl_id),]
mycounts$symbol <- d$symbol
mycounts<-subset(mycounts,symbol!="NA") #去缺失值
rownames(mycounts) <- mycounts$symbol
R分析前需要准备的两个文件:
featurecounts计数文件与分组文件
代码部分
DEG分析
library(DESeq2)
setwd("E:/R/DEseq2")
mycounts <- read.csv("counts.csv",header= TRUE,row.names = 2)
mycounts <- mycounts[rowSums(mycounts[-1])!=0,]
mycounts <- mycounts[-1]
mymeta <- read.csv("mymeta heathly_vs_covid.csv",stringsAsFactors = T)
colnames(mycounts)==mymeta$id
dds <- DESeqDataSetFromMatrix(countData = mycounts, colData = mymeta,desig=~dex)
dds <- DESeq(dds)
res <- results(dds,contrast = c("dex","covid","Healthy"))
res <- data.frame(res)
DEG <- res[order(res$padj),] #按照padj排序
write.csv(DEG,"DEG.csv",quote = F)
save(DEG,file = "DEG_results.Rdata") #保存R数据方便下次继续使用
得到的DEG结果
heatmap
library(pheatmap)
choose_gene=head(rownames(DEG),1000)
choose_matrix=mycounts[choose_gene,]
choose_matrix <- log2(choose_matrix+1)
choose_matrix=t(scale(t(choose_matrix)))
group_list <-c(rep("covid",17),rep("Healthy",19))
ac <- data.frame(dex=group_list)
rownames(ac) <- colnames(choose_matrix)
pheatmap(choose_matrix,filename = "heatmap.png", show_rownames = F, show_colnames = F,
annotation_col = ac, display_numbers = FALSE)
volcano
library(ggpubr)
library(ggthemes)
DEG$change =as.factor(ifelse(DEG$pvalue < 0.05 & DEG$log2FoldChange > 2,'UP',
ifelse(DEG$pvalue < 0.05 & DEG$log2FoldChange < -2,'DOWN',
"NOT")))
DEG$logp = -log10(DEG$pvalue)
table(DEG$change)
DEG$label <- ""
DEG <- DEG[order(DEG$pvalue),]
up_genes <- head(row.names(DEG)[which(DEG$change == "UP")],10)
down_genes <- head(row.names(DEG)[which(DEG$change =="DOWN")],10)
DEG_top10 <- c(as.character(up_genes),as.character(down_genes))
DEG$label[match(DEG_top10,row.names(DEG))] <- DEG_top10
ggscatter(DEG, x = "log2FoldChange", y = "logp",
color = "change",
palette = c("#2f5688","#BBBBBB","#CC0000"),
size = 1,
label = DEG$label,
font.label = 8,
repel = T,
xlab = "log2FoldChange",
ylab ="-log10(adjust p value)") + theme_base() +
geom_hline(yintercept = 1.5,linetype="dashed")+
geom_vline(xintercept = c(-1,1),linetype="dashed")
ggsave("volcano.png",dpi=600)
GO And KEGG
#####install packages#####
BiocManager::install("clusterProfiler")
BiocManager::install("topGO")
BiocManager::install("Rgraphviz")
BiocManager::install("pathview")
BiocManager::install("org.Hs.eg.db")
library(clusterProfiler)
library(topGO)
library(Rgraphviz)
library(pathview)
library(org.Hs.eg.db)
DEG_vector <- (DEG$padj < 0.005 & DEG$log2FoldChange > 3)|(DEG$padj < 0.005 & DEG$log2FoldChange < -3) #Padj根据需要改为pvalue,所有数值可以根据需求更改。
DEG.sign <- DEG[DEG_vector,]
DEG.entrez_id = mapIds(x = org.Hs.eg.db,
keys = rownames(DEG.sign),
keytype = "SYMBOL",
column = "ENTREZID")
DEG.sign$ENTREZID <- DEG.entrez_id
gene_up <- DEG.sign[DEG.sign$change == 'UP','ENTREZID']
gene_down <- DEG.sign[DEG.sign$change == 'DOWN','ENTREZID']
source('kegg_and_go_up_and_down.R') #提前准备好kegg_and_go_up_and_down.R文件
run_go(gene_up,gene_down,pro='convid_VS_healthy')
run_kegg(gene_up,gene_down,pro='convid_VS_healthy')
kegg_and_go_up_and_down.R
(via jimmy)
## KEGG pathway analysis
### 做KEGG数据集超几何分布检验分析,重点在结果的可视化及生物学意义的理解。
run_kegg <- function(gene_up,gene_down,geneList=F,pro='test'){
gene_up=unique(gene_up)
gene_down=unique(gene_down)
gene_diff=unique(c(gene_up,gene_down))
### over-representation test
# 下面把3个基因集分开做超几何分布检验
# 上调基因集。
kk.up <- enrichKEGG(gene = gene_up,
organism = 'hsa',
#universe = gene_all,
pvalueCutoff = 0.5,
qvalueCutoff = 0.5)
head(kk.up)[,1:6]
kk=kk.up
dotplot(kk)
kk=DOSE::setReadable(kk, OrgDb='org.Hs.eg.db',keyType = "ENTREZID")
write.csv(kk@result,paste0("./kegg_results/",pro,'_kk.up.csv'))
# 下调基因集。
kk.down <- enrichKEGG(gene = gene_down,
organism = 'hsa',
#universe = gene_all,
pvalueCutoff = 0.5,
qvalueCutoff =0.5)
head(kk.down)[,1:6]
kk=kk.down
dotplot(kk)
kk=DOSE::setReadable(kk, OrgDb='org.Hs.eg.db',keyType = "ENTREZID")
write.csv(kk@result,paste0("./kegg_results/",pro,'_kk.down.csv'))
# 上下调合并后的基因集。
kk.diff <- enrichKEGG(gene = gene_diff,
organism = 'hsa',
pvalueCutoff = 0.5)
head(kk.diff)[,1:6]
kk=kk.diff
dotplot(kk)
kk=DOSE::setReadable(kk, OrgDb='org.Hs.eg.db',keyType = "ENTREZID")
write.csv(kk@result,paste0("./kegg_results/",pro,'_kk.diff.csv'))
kegg_diff_dt <- as.data.frame(kk.diff)
kegg_down_dt <- as.data.frame(kk.down)
kegg_up_dt <- as.data.frame(kk.up)
down_kegg<-kegg_down_dt[kegg_down_dt$pvalue<0.1,];down_kegg$group=-1
up_kegg<-kegg_up_dt[kegg_up_dt$pvalue<0.1,];up_kegg$group=1
#画图设置, 这个图很丑,大家可以自行修改。
g_kegg=kegg_plot(up_kegg,down_kegg)
print(g_kegg)
ggsave(g_kegg,filename = paste0("./kegg_results/",pro,'_kegg_up_down.png'))
if(geneList){
### GSEA
## GSEA算法跟上面的使用差异基因集做超几何分布检验不一样。
kk_gse <- gseKEGG(geneList = geneList,
organism = 'hsa',
nPerm = 1000,
minGSSize = 20,
pvalueCutoff = 0.9,
verbose = FALSE)
head(kk_gse)[,1:6]
gseaplot(kk_gse, geneSetID = rownames(kk_gse[1,]))
gseaplot(kk_gse, 'hsa04110',title = 'Cell cycle')
kk=DOSE::setReadable(kk_gse, OrgDb='org.Hs.eg.db',keytype='ENTREZID')
tmp=kk@result
write.csv(kk@result,paste0(pro,'_kegg.gsea.csv'))
# 这里如果找不到显著下调的通路,可以选择调整阈值,或者其它。
down_kegg<-kk_gse[kk_gse$pvalue<0.01 & kk_gse$enrichmentScore < 0,];down_kegg$group=-1
up_kegg<-kk_gse[kk_gse$pvalue<0.01 & kk_gse$enrichmentScore > 0,];up_kegg$group=1
g_kegg=kegg_plot(up_kegg,down_kegg)
print(g_kegg)
ggsave(g_kegg,filename = paste0("./kegg_results/",pro,'_kegg_gsea.png'))
}
}
### GO database analysis
### 做GO数据集超几何分布检验分析,重点在结果的可视化及生物学意义的理解。
run_go <- function(gene_up,gene_down,pro='test'){
gene_up=unique(gene_up)
gene_down=unique(gene_down)
gene_diff=unique(c(gene_up,gene_down))
g_list=list(gene_up=gene_up,
gene_down=gene_down,
gene_diff=gene_diff)
# 因为go数据库非常多基因集,所以运行速度会很慢。
if(T){
go_enrich_results <- lapply( g_list , function(gene) {
lapply( c('BP','MF','CC') , function(ont) {
cat(paste('Now process ',ont ))
ego <- enrichGO(gene = gene,
#universe = gene_all,
OrgDb = org.Hs.eg.db,
ont = ont ,
pAdjustMethod = "BH",
pvalueCutoff = 0.5,
qvalueCutoff = 0.5,
readable = TRUE)
print( head(ego) )
return(ego)
})
})
save(go_enrich_results,file =paste0(pro, '_go_enrich_results.Rdata'))
}
# 只有第一次需要运行,就保存结果哈,下次需要探索结果,就载入即可。
load(file=paste0(pro, '_go_enrich_results.Rdata'))
n1= c('gene_up','gene_down','gene_diff')
n2= c('BP','MF','CC')
for (i in 1:3){
for (j in 1:3){
fn=paste0("./go_enrich_results/",pro, '_dotplot_',n1[i],'_',n2[j],'.png')
cat(paste0(fn,'\n'))
# png(fn,res=150,width = 1080)
# print( dotplot(go_enrich_results[[i]][[j]] ))
#dev.off()
dotplot(go_enrich_results[[i]][[j]] )
ggsave(fn)
}
}
}
kegg_plot <- function(up_kegg,down_kegg){
dat=rbind(up_kegg,down_kegg)
colnames(dat)
dat$pvalue = -log10(dat$pvalue)
dat$pvalue=dat$pvalue*dat$group
dat=dat[order(dat$pvalue,decreasing = F),]
g_kegg<- ggplot(dat, aes(x=reorder(Description,order(pvalue, decreasing = F)), y=pvalue, fill=group)) +
geom_bar(stat="identity") +
scale_fill_gradient(low="blue",high="red",guide = FALSE) +
scale_x_discrete(name ="Pathway names") +
scale_y_continuous(name ="log10P-value") +
coord_flip() + theme_bw()+theme(plot.title = element_text(hjust = 0.5))+
ggtitle("Pathway Enrichment")
}