transcript整合为gene表达值,tximport到底干了啥...

  有些问题来来回回,学了忘,忘了学,反反复复很多次,用到时依然是模糊的。之所以被遗忘,也许是问题本身不重要,没有什么存在感;也许是要学的东西很多,脑容量不够。Anyway,既然记不住,那只能动动手记下来了,以便日后疑惑时有迹可循。

  RNA-seq数据定量流程使用的软件一直是kallisto,用过的人都知道其定量的结果为转录本表达值,可是通常情况下,大家需要的还是基因层面的表达量,因此,转录本定量整合为基因表达值无可避免。

  整合可以借助R包tximport轻松完成,用过的都知道该包可以轻松搞定SalmonAlevinkallistoRSEMStringTie软件结果的整合,几行代码运行下来便将转录本表达值整合为基因水平。

library(tximport)

files <- list.files('result', '*.tsv', full.names=T, recursive=T)
names(files) <- sapply(strsplit(basename(files), split='\\.'), function(x) x[1])
files
                                ctrl1
    "result/ctrl1/kallisto/ctrl1.tsv"                                                                                                            
                                ctrl2
    "result/ctrl2/kallisto/ctrl2.tsv"                                                                                                             
                                ctrl3
    "result/ctrl3/kallisto/ctrl3.tsv"                                                                                                        
                              stroke1
"result/stroke1/kallisto/stroke1.tsv"                                                                                                        
                              stroke2
"result/stroke2/kallisto/stroke2.tsv"                                                                                                        
                              stroke3
"result/stroke3/kallisto/stroke3.tsv"

tx2gene <- read.table('gencode_hg38_tx2g.txt', header=T, sep="\t")
head(tx2gene)
               ENST              ENSG
1 ENST00000456328.2 ENSG00000223972.5
2 ENST00000450305.2 ENSG00000223972.5
3 ENST00000488147.1 ENSG00000227232.5
4 ENST00000619216.1 ENSG00000278267.1
5 ENST00000473358.1 ENSG00000243485.5
6 ENST00000469289.1 ENSG00000243485.5

txi <- tximport(files, type="kallisto", tx2gene=tx2gene, ignoreAfterBar=T)
str(txi)
List of 4
 $ abundance          : num [1:60669, 1:6] 0.145 0 4.455 3.331 1.435 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:60669] "ENSG00000000003.15" "ENSG00000000005.6" "ENSG00000000419.12" "ENSG00000000457.14" ...
  .. ..$ : chr [1:6] "ctrl1" "ctrl2" "ctrl3" "stroke1" ...
 $ counts             : num [1:60669, 1:6] 34.6 0 253 618.7 262.2 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:60669] "ENSG00000000003.15" "ENSG00000000005.6" "ENSG00000000419.12" "ENSG00000000457.14" ...
  .. ..$ : chr [1:6] "ctrl1" "ctrl2" "ctrl3" "stroke1" ...
 $ length             : num [1:60669, 1:6] 3516 642 835 2732 2689 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : chr [1:60669] "ENSG00000000003.15" "ENSG00000000005.6" "ENSG00000000419.12" "ENSG00000000457.14" ...
  .. ..$ : chr [1:6] "ctrl1" "ctrl2" "ctrl3" "stroke1" ...
 $ countsFromAbundance: chr "no"

  整合时需要一个tx2gene表格,内容为转录本id与基因id的对应关系。tximport整合生成的是一个列表,里面包含四个结果,前面三个分别是TPM、原始count、基因长度。countsFromAbundance指定整合原始count的方法,默认为no

  虽然整合的流程做起来很轻松,但背后具体是怎么将转录本表达值合并为基因水平的呢?基因的表达值是不是转录本表达值的简单加和?下面一起来拭目以待。如果countsFromAbundance选定了某个方法,则用矫正后的abundance去估计原始count,然后整合为基因水平。如没有选择矫正方法,则直接整合为基因水平。下面以样本ctrl1为例,演示一下默认情况下整合的核心过程:

ctrl1 <- read.table("result/ctrl1/kallisto/ctrl1.tsv", stringsAsFactors=F, header=T, sep='\t')
ctrl1$target_id <- sapply(strsplit(ctrl1$target_id, split='\\|'), function(x) x[2])
head(ctrl1)
          target_id length eff_length est_counts      tpm
1 ENSG00000223972.5   1657   1405.040   166.5320 1.743560
2 ENSG00000223972.5    632    380.273     0.0000 0.000000
3 ENSG00000227232.5   1351   1099.040    45.7171 0.611919
4 ENSG00000278267.1     68     25.760     0.0000 0.000000
5 ENSG00000243485.5    712    460.158     0.0000 0.000000
6 ENSG00000243485.5    535    283.436     0.0000 0.000000

abundanceMat <- rowsum(ctrl1[,'tpm'], ctrl1$target_id)
countsMat <- rowsum(ctrl1[,'est_counts'], ctrl1$target_id)

weightedLength <- rowsum(ctrl1[,'tpm'] * ctrl1[,'eff_length'], ctrl1$target_id)
lengthMat <- weightedLength/abundanceMat

  从计算过程可知,默认情况下直接将各转录本加和作为基因的表达值,基因长度则为加权平均值。下面可以对比一下结果:

# abundance
identical(abundanceMat[,1], txi$abundance[,'ctrl1'])
[1] TRUE

head(abundanceMat)
                         [,1]
ENSG00000000003.15   0.144553
ENSG00000000005.6    0.000000
ENSG00000000419.12   4.454973
ENSG00000000457.14   3.331466
ENSG00000000460.17   1.434763
ENSG00000000938.13 141.169300

head(txi$abundance[,'ctrl1', drop=F])
                        ctrl1
ENSG00000000003.15   0.144553
ENSG00000000005.6    0.000000
ENSG00000000419.12   4.454973
ENSG00000000457.14   3.331466
ENSG00000000460.17   1.434763
ENSG00000000938.13 141.169300

# count
identical(countsMat[,1], txi$counts[,'ctrl1'])
[1] TRUE

head(countsMat)
                         [,1]
ENSG00000000003.15    34.5503
ENSG00000000005.6      0.0000
ENSG00000000419.12   253.0003
ENSG00000000457.14   618.7436
ENSG00000000460.17   262.2473
ENSG00000000938.13 17233.0064

head(txi$counts[,'ctrl1', drop=F])
                        ctrl1
ENSG00000000003.15    34.5503
ENSG00000000005.6      0.0000
ENSG00000000419.12   253.0003
ENSG00000000457.14   618.7436
ENSG00000000460.17   262.2473
ENSG00000000938.13 17233.0064

# length
head(lengthMat)
                        [,1]
ENSG00000000003.15 3516.0400
ENSG00000000005.6        NaN
ENSG00000000419.12  835.4205
ENSG00000000457.14 2732.1483
ENSG00000000460.17 2688.8169
ENSG00000000938.13 1795.7674

head(txi$length[,'ctrl1', drop=F])
                       ctrl1
ENSG00000000003.15 3516.0400
ENSG00000000005.6   642.3992
ENSG00000000419.12  835.4205
ENSG00000000457.14 2732.1483
ENSG00000000460.17 2688.8169
ENSG00000000938.13 1795.7674

  可以看到abundancecount的结果与软件完全一致,length除了有些缺失值,其余也一致。整合多个样本时,软件对于长度缺失值的处理如下:

aveLengthSamp <- rowMeans(lengthMatTx)
aveLengthSampGene <- tapply(aveLengthSamp, geneId, mean)
lengthMat <- replaceMissingLength(lengthMat, aveLengthSampGene)

  先计算样本间每个转录本长度的平均值,然后基于计算每个基因所有转录本的长度的平均值,作为基因的长度,用于填充缺失值。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容