獲取基因有效長度的N種方法

在RNAseq的下游分析中贬丛,一般都會將上游處理完得到的原始counts數(shù)轉(zhuǎn)變?yōu)镕PKM/RPKM或是TPM來進行后續(xù)的展示或分析,其定義和計算公式在我之前的文章中有所總結(jié)Counts FPKM RPKM TPM 的轉(zhuǎn)化 - 簡書 (jianshu.com)
需要注意一點的是储玫,在計算FPKM/RPKM和TPM時澎羞,基因長度一般指的都是基因有效長度effective length,即該基因的外顯子總長度或轉(zhuǎn)錄本總長度锅锨,以此為標準來消除測序造成的基因長度影響才更為準確螺句。參見生信技能樹文章:基因長度之多少 | 生信菜鳥團 (bio-info-trainee.com)

那么問題來了,在計算FPKM/RPKM時橡类,每個基因的基因有效長度數(shù)據(jù)該如何獲取呢蛇尚?
我總結(jié)了幾種獲取基因有效長度(或非冗余總外顯子長度、總轉(zhuǎn)錄本長度)的方法顾画,現(xiàn)整理如下:

一取劫、從上游輸出文件結(jié)果中獲取基因有效長度

一般而言匆笤,RNA-seq得到原始counts表達矩陣最常用到的上游軟件就是featureCounts和Salmon了,在這兩類軟件的輸出結(jié)果中谱邪,除了基因(或轉(zhuǎn)錄本)的counts信息外炮捧,也包含了基因有效長度信息,如featureCounts輸出文件的Length這一列對應的就是基因有效長度惦银。(P.S. 之前一直以為featureCounts的Length只是單純的基因長度咆课,后來經(jīng)過多種方法比較后發(fā)現(xiàn)其實Length這一列就已經(jīng)是基因的有效長度了...在文章后面我也會展示這幾種方法比較的結(jié)果)

因此,最方便的做法就是在下游獲取counts矩陣時扯俱,將基因有效長度信息也同時提取出來用于后續(xù)的基因表達量轉(zhuǎn)化书蚪。

1. 針對featureCounts的輸出文件

在R中讀取featureCounts的輸出文件,提取Length和對應的geneid信息迅栅,再按照counts中的rowname(geneid)匹配排序殊校,即可進行后續(xù)的TPM、FPKM值的計算了读存。


featurecounts輸出文件格式
rm(list=ls())
options(stringsAsFactors = F) 
library(tidyverse) # ggplot2 stringer dplyr tidyr readr purrr  tibble forcats
library(data.table) #可多核讀取文件

a1 <- fread('counts.txt', header = T, data.table = F)#載入counts为流,第一列設置為列名

### counts矩陣的構(gòu)建
counts <- a1[,7:ncol(a1)] #截取樣本基因表達量的counts部分作為counts 
rownames(counts) <- a1$Geneid #將基因名作為行名

### 從featurecounts 原始輸出文件counts.txt中提取Geneid、Length(轉(zhuǎn)錄本長度)让簿,
geneid_efflen <- subset(a1,select = c("Geneid","Length"))
       colnames(geneid_efflen) <- c("geneid","efflen")  
geneid_efflen_fc <- geneid_efflen #用于之后比較

### 取出counts中g(shù)eneid的對應的efflen
dim(geneid_efflen)
efflen <- geneid_efflen[match(rownames(counts),
                              geneid_efflen$geneid),
                        "efflen"]

### 計算 TPM
#TPM (Transcripts Per Kilobase Million)  每千個堿基的轉(zhuǎn)錄每百萬映射讀取的Transcripts
counts2TPM <- function(count=count, efflength=efflen){
  RPK <- count/(efflength/1000)       #每千堿基reads (“per million” scaling factor) 長度標準化
  PMSC_rpk <- sum(RPK)/1e6        #RPK的每百萬縮放因子 (“per million” scaling factor ) 深度標準化
  RPK/PMSC_rpk                    
  }  
tpm <- as.data.frame(apply(counts,2,counts2TPM))
colSums(tpm)

其中g(shù)eneid_efflen內(nèi)容如下
geneid_efflen

2. 針對Salmon的輸出文件

Salmon的輸出結(jié)果以及各內(nèi)容的解釋如下敬察。Salmon Output File Formats - Salmon 1.8.0 documentation
值得注意的是,salmon不僅給出了基因有效長度Length(轉(zhuǎn)錄本長度)尔当,還給出了EffectiveLength莲祸,即經(jīng)過考慮各種因素矯正后的轉(zhuǎn)錄本有效長度。官方更推薦使用EffectiveLength進行后續(xù)的分析居凶,它結(jié)果中的TPM值也是根據(jù)EffectiveLength計算的虫给。

Salmon的輸出結(jié)果

Salmon的輸出結(jié)果官方解釋

我們一般使用tximport導入salmon的輸出文件“quant.sf”(轉(zhuǎn)錄本的統(tǒng)計結(jié)果)和轉(zhuǎn)錄本id與gene symbol對應關(guān)系文件,會生成以下幾個數(shù)據(jù):
"abundance" "counts" "length" "countsFromAbundance"
tximport生成的Length就是EffectiveLength侠碧,而"abundance" 就是TPM值抹估,我們提取Length用于后續(xù)計算FPKM。注意弄兜,由于每個樣本中基因的EffectiveLength有差異药蜻,我們要提取的實際為EffectiveLength的矩陣(或者可以每行EffectiveLength取均值)。

library(tximport) 

#t2s為從gtf文件中提取的transcript_id和symbol的對應關(guān)系文件
t2s <- fread("t2s_vm29_gencode.txt", data.table = F, header = F) 

##創(chuàng)建quant.sf所在路徑  導入salmon文件處理匯總
quantdir <- file.path(getwd(),'salmon'); quantdir
files <- list.files(pattern="*quant.sf",quantdir,recursive=T); files  #顯示目錄下所有符合要求的文件
files <- file.path(quantdir,files);files
txi_gene <- tximport(files, type = "salmon", tx2gene = t2s)

##提取出counts/tpm表達矩陣
counts <- apply(txi_gene$counts,2,as.integer) #將counts數(shù)取整
rownames(counts) <- rownames(txi_gene$counts)
tpm <- txi_gene$abundance  ###abundance為基因的Tpm值

###提取geneid_efflen_mat
geneid_efflen_mat <- txi_gene$length  ###Length為基因的轉(zhuǎn)錄本有效長度

## 計算 TPM 替饿、FPKM
  if (F) { #可直接從txi的"abundance"  中提取语泽,不用運行
    tpm <- data.frame(rownames(counts),row.names = rownames(counts))
    for (i in 1:ncol(counts)) {
      count <- counts[,i] 
      efflength <- geneid_efflen_mat[,i]
      RPK <- count/(efflength/1000)   #每千堿基reads (reads per million) 長度標準化
      PMSC_rpk <- sum(RPK)/1e6        #RPK每百萬縮放因子 (“per million” scaling factor ) 深度標準化
      tpm00 <- RPK/PMSC_rpk  
      tpm <- data.frame(tpm,tpm00)
      rm(tpm00)
    }
    tpm <- tpm[,-1];  colnames(tpm) <- colnames(counts);  head(tpm)
   
  }
  
  ## 計算 fpkm
  if(T){
    fpkm <- data.frame(rownames(counts),row.names = rownames(counts))
    for (i in 1:ncol(counts)) {
      count <- counts[,i] 
      efflength <- geneid_efflen_mat[,i]
      PMSC_counts <- sum(count)/1e6   #counts的每百萬縮放因子 (“per million” scaling factor) 深度標準化
      FPM <- count/PMSC_counts        #每百萬reads/Fragments (Reads/Fragments Per Million) 長度標準化
      fpkm00 <- FPM/(efflength/1000)
      fpkm <- data.frame(fpkm,fpkm00)
      rm(fpkm00)
    }
    fpkm <- fpkm[,-1];  colnames(fpkm) <- colnames(counts)
  }

如果想要提取一般意義上的基因有效長度,需要利用“quant.genes.sf”文件(基因的統(tǒng)計結(jié)果视卢,需要在進行salmon時加上參數(shù) -g 踱卵,后接gtf文件),提取Length這一列的信息。

a2 <- fread("quant.genes.sf",
            data.table = F)
geneid_efflen <- subset(a2, select = c("Name","Length"))
colnames(geneid_efflen) <- c("geneid","efflen") 
geneid_efflen_salmon <- geneid_efflen #用于之后比較

二惋砂、 從gtf文件中計算獲取基因有效長度

整理了兩種從gtf文件中計算獲取基因有效長度的方法(非冗余外顯子長度之和)妒挎,參考這兩篇文章:
基因長度并不是end-start - 簡書 (jianshu.com)
Htseq Count To Fpkm | KeepNotes blog (bioinfo-scrounger.com)
由于處理數(shù)據(jù)量很大,代碼速度運行較慢西饵,因此在以下代碼中還調(diào)用了parallel包進行多核運算處理

1. 利用GenomicFeatures包導入gtf處理

library(parallel) #并行計算  parApply parLapply parSaplly 
cl <- makeCluster(0.75*detectCores())  #設計啟用計算機3/4的核

## 利用GenomicFeatures包導入gtf處理
    library(GenomicFeatures)
    txdb <- makeTxDbFromGFF("gencode.vM25.chr_patch_hapl_scaff.annotation.gtf.gz",
 format="gtf") 
    exons_gene <- exonsBy(txdb, by = "gene") ###提取基因外顯子
    head(exons_gene)

    ##計算總外顯子長度:用reduce去除掉重疊冗余的部分酝掩,,width統(tǒng)計長度,最后計算總長度
    exons_gene_lens <- parLapply(cl,exons_gene,function(x){sum(width(reduce(x)))}) 
    exons_gene_lens[1:10]
    
    ##轉(zhuǎn)換為dataframe
    geneid_efflen <- data.frame(geneid=names(exons_gene_lens),
                                efflen=as.numeric(exons_gene_lens))
    geneid_efflen_gtf1 <- geneid_efflen

2.利用rtracklayer包導入gtf處理

##利用rtracklayer包import導入處理 
    gtf <- as.data.frame(rtracklayer::import("gencode.vM25.chr_patch_hapl_scaff.annotation.gtf.gz"))
    table(gtf$type)

    exon <- gtf[gtf$type=="exon",
                c("start","end","gene_id")]
    exon_bygeneid <- split(exon,exon$gene_id)   #按照每個geneid所含的exon排序成列表
    
    efflen <- parLapply(cl,exon_bygeneid,function(x){
      tmp <- apply(x,1,function(y){  y[1]:y[2]  }) #輸出exon長度值的所有元素            
      length(unique(unlist(tmp))) #去重復并統(tǒng)計exon長度元素的數(shù)量
      }) 

    ##轉(zhuǎn)換為dataframe
    geneid_efflen <- data.frame(geneid=names(efflen),
                                efflen=as.numeric(efflen))
    geneid_efflen_gtf2 <- geneid_efflen

所得結(jié)果的比較

現(xiàn)在就可以來進行基因有效長度之間的比較啦眷柔。
首先看看從gtf文件中獲取基因有效長度的兩種方法是否有差異期虾。可以發(fā)現(xiàn)驯嘱,僅有極少數(shù)efflen有差異镶苞,因此這兩種方法可以說是幾乎沒什么差別了:


從gtf文件中獲取efflen的比較

再比較一下geneid_efflen_gtf1和geneid_efflen_salmon,發(fā)現(xiàn)有一半的efflen是不匹配的宙拉?仔細一想這也是可以理解的宾尚,因為上游中salmon是對樣本中的轉(zhuǎn)錄本進行的統(tǒng)計丙笋,這說明了樣本中有一半的基因并未表達其全部的轉(zhuǎn)錄本而已:


salmon和gtf中獲取的efflen比較

再將geneid_efflen_gtf1和geneid_efflen_fc進行比較谢澈,發(fā)現(xiàn)全都能匹配上,這說明featureCounts的Length確實就已經(jīng)是我們想要的基因有效長度了(即非冗余外顯子總長度):


featureCounts和gtf中獲取的efflen比較

總結(jié)

  1. 獲取基因有效長度的最簡便方法是直接從featureCounts或salmon的輸出文件中提取御板。
    但需要注意的是锥忿,featureCounts中基因有效長度Length即為基因的非冗余外顯子總長度,而salmon中的基因有效長度Length是目標基因的轉(zhuǎn)錄本總長度怠肋,由于樣本中只有部分基因會表達其全部類型的轉(zhuǎn)錄本敬鬓,因此salmon中的轉(zhuǎn)錄本總長度會有部分小于非冗余外顯子總長度。
  2. salmon輸出結(jié)果中不僅給出了基因有效長度Length(轉(zhuǎn)錄本總長度)笙各,還給出了經(jīng)過考慮各種因素矯正后的轉(zhuǎn)錄本有效長度EffectiveLength。Salmon官方更推薦使用EffectiveLength進行后續(xù)的分析,認為其能更好消除測序時基因長度的影響汉额,它結(jié)果中的TPM值也是根據(jù)EffectiveLength計算的庆捺,后續(xù)分析中可以直接采用。
  3. 在沒有上游原始輸出文件的情況下惶楼,也可以采取直接從gtf文件中計算的方法右蹦,獲取每個基因的非冗余外顯子總長度得到基因有效長度。還可以保存geneid_efflen便于之后再讀燃呔琛:
    write.csv(geneid_efflen,file = "geneid_efflen_vm25_gencode.csv",row.names = F)

參考資料
基因長度之多少 | 生信菜鳥團 (bio-info-trainee.com)
Counts FPKM RPKM TPM 的轉(zhuǎn)化 - 簡書 (jianshu.com)
基因長度并不是end-start - 簡書 (jianshu.com)
Htseq Count To Fpkm | KeepNotes blog (bioinfo-scrounger.com)
Salmon Output File Formats - Salmon 1.8.0 documentation

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末何陆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子豹储,更是在濱河造成了極大的恐慌贷盲,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剥扣,死亡現(xiàn)場離奇詭異巩剖,居然都是意外死亡慨灭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門球及,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氧骤,“玉大人,你說我怎么就攤上這事吃引〕锪辏” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵镊尺,是天一觀的道長朦佩。 經(jīng)常有香客問我,道長庐氮,這世上最難降的妖魔是什么语稠? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮弄砍,結(jié)果婚禮上仙畦,老公的妹妹穿的比我還像新娘。我一直安慰自己音婶,他們只是感情好慨畸,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衣式,像睡著了一般寸士。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碴卧,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天弱卡,我揣著相機與錄音,去河邊找鬼住册。 笑死婶博,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的界弧。 我是一名探鬼主播凡蜻,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垢箕!你這毒婦竟也來了划栓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤条获,失蹤者是張志新(化名)和其女友劉穎忠荞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡委煤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年堂油,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碧绞。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡府框,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讥邻,到底是詐尸還是另有隱情迫靖,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布兴使,位于F島的核電站系宜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏发魄。R本人自食惡果不足惜盹牧,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望励幼。 院中可真熱鬧汰寓,春花似錦、人聲如沸赏淌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽六水。三九已至,卻和暖如春辣卒,著一層夾襖步出監(jiān)牢的瞬間掷贾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工荣茫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留想帅,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓啡莉,卻偏偏與公主長得像港准,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咧欣,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 字符串 1.什么是字符串 使用單引號或者雙引號括起來的字符集就是字符串浅缸。 引號中單獨的符號、數(shù)字魄咕、字母等叫字符衩椒。 ...
    mango_2e17閱讀 7,495評論 1 7
  • 《閉上眼睛才能看清楚自己》這本書是香海禪寺主持賢宗法師的人生體悟,修行心得及講學錄,此書從六個章節(jié)講述了禪修是什么...
    宜均閱讀 9,984評論 1 25
  • 偶然間從公眾號里看見了小白訓練營的課毛萌。就點進去看了看苟弛。剛開始的時候我覺得就是騙人的。后來一想阁将,學費那么少膏秫。干嘛...
    天天優(yōu)惠233閱讀 3,689評論 0 12
  • 前言 Google Play應用市場對于應用的targetSdkVersion有了更為嚴格的要求。從 2018 年...
    申國駿閱讀 63,945評論 14 98
  • 第七章:理性的投資觀 字數(shù): 1.投資要圍繞目的進行 投資的目的是為了掙錢做盅。投資的除了金錢還有時間和精力也是一種投...
    幸福萍寶閱讀 3,317評論 1 2