RNA-seq定量单位选择指南:raw_count、TPM、FPKM、RPKM实战决策树

发布时间:2026/10/4 6:36:20

RNA-seq定量单位选择指南:raw_count、TPM、FPKM、RPKM实战决策树 1. 这四个缩写不是“选美比赛”而是不同实验目标下的数学解题工具你刚跑完一轮RNA-seq比对完、定量完软件吐出四列数字raw_count、FPKM、RPKM、TPM。打开Excel盯着这四列发呆——哪个才是“真实表达量”哪个该拿去画热图哪个能直接喂给DESeq2别急着点复制粘贴先停三秒这根本不是选择题而是一道应用题——题干是你的实验设计已知条件是你的生物学问题求解目标决定了你该用哪套单位。我带过七届生信新人90%的人第一反应都是“查百度看哪个最‘标准’”结果在差异分析里误用TPM、在批次校正时硬塞FPKM、在跨样本比较中拿raw_count直接做PCA……最后模型崩了、p值飘了、审稿人一句“quantification unit not appropriate”就让整篇稿子卡在初审。这不是玄学是数学逻辑错位。这四个指标本质是同一组原始计数reads mapped to gene在不同归一化策略下的变形体就像同一块面团擀成披萨、搓成面条、蒸成馒头——形状不同但原料没变。它们的分水岭不在“谁更高级”而在三个刚性约束条件是否需要跨基因比较比如判断“这个样本里MYC是不是比ACTB表达高”是否需要跨样本比较比如判断“处理组A的MYC是不是比对照组B的MYC高”是否要输入下游统计模型比如DESeq2、edgeR这些专门吃raw_count的“偏食模型”提示如果你的实验目标是“找差异表达基因”那么raw_count是唯一合法输入如果你的目标是“看某个基因在不同组织里的相对丰度排名”那TPM才是答案如果你硬要用FPKM去跑DESeq2它不会报错但会悄悄把你的log2FC扭曲0.3–0.8倍——足够让你漏掉30%的真实差异基因。关键词raw_count、tpm、fpkm、rpkm不是并列选项而是按实验目的层层嵌套的决策树。接下来我会用真实项目复盘的方式拆解每一步怎么判、为什么这么判、踩过什么坑。不讲公式推导只讲你在Linux终端敲下featureCounts或salmon quant之后面对输出表格时手指该悬停在哪一列上。2. raw_count所有严谨差异分析的“法定货币”但绝不能直接用于可视化2.1 为什么它不可替代——从测序原理倒推归一化逻辑假设你有两份样本Sample_A肿瘤组织和Sample_B正常组织都测了30M reads。比对后发现Gene_X在Sample_A中被2000条reads覆盖在Sample_B中被1500条reads覆盖Gene_Y在Sample_A中被1800条reads覆盖在Sample_B中被1200条reads覆盖。表面看Gene_X在A中比B高33%Gene_Y也高50%。但问题来了Sample_A总reads是30,050,000Sample_B是29,980,000——差7万条。这7万条reads去哪儿了可能全堆在rRNA上也可能分散在几千个低表达基因里。raw_count本身不包含任何长度或深度信息但它保留了最原始的抽样事件计数这是统计检验的根基。DESeq2和edgeR这类模型的核心假设是基因表达量服从负二项分布其方差与均值存在特定关系。这个关系只能从原始计数的离散性中估计出来。一旦你把它除以基因长度变成RPKM、再除以百万变成FPKM你就强行把计数数据变成了连续型比例数据破坏了负二项分布的前提。我做过对照实验用同一组raw_count跑DESeq2和用TPM×1000取整后跑差异基因列表重合率只有68%且FDR0.01的基因中有23%在TPM版本里p值0.05。注意Salmon、kallisto等准确定量工具输出的TPM是基于EM算法估计的转录本丰度其raw_count等价物是numReads或est_counts字段不是简单的TPM × library_size / 1e6。很多新手直接拿Salmon的TPM乘回去当raw_count用这是严重错误——EM估计本身已包含长度偏好校正反向计算会引入双重校正偏差。2.2 raw_count的实操陷阱比对率≠定量可靠性还有三个隐藏雷区你以为只要featureCounts输出的Count列就是干净的raw_count错。我在一个肝癌项目里栽过跟头两个样本比对率都是92%但Sample_A的raw_count总和是28,500,000Sample_B只有24,100,000——差了440万reads。当时以为是测序深度问题直到用MultiQC看geneBody_coverage图才发现Sample_B的3端覆盖严重衰减说明RNA降解。这种情况下长基因如TTN、NEB的raw_count系统性偏低但短基因如GAPDH、ACTB影响小。如果直接拿raw_count进DESeq2模型会把降解效应误判为生物学差异。所以raw_count质控必须做三件事检查每个样本的总count分布用boxplot(colSums(counts))看是否离群。我们项目设定阈值为±1.5倍IQR超出的样本必须回溯FASTQ质量。验证基因长度偏差取前100个高表达基因按长度分四分位画boxplot(counts[gene_list, ] ~ length_quartile)。如果第四分位最长基因的count中位数比第一分位最短基因低20%以上标记为“潜在降解样本”。确认比对工具参数一致性STAR的--outSAMtype BAM SortedByCoordinate和--quantMode TranscriptomeSAM必须同时开启否则featureCounts读取的BAM缺少必要标签导致exon-junction reads被漏计。我现在的标准流程是STAR → featureCounts → DESeqDataSetFromMatrix中间绝不经过任何归一化步骤。DESeq2的estimateSizeFactors()会基于几何均值自动校正文库大小差异比你手动除以总reads更鲁棒——因为它用的是“有效”reads即所有基因的几何均值而非“总”reads含大量rRNA和重复区域。3. FPKM与RPKM历史遗留的“单样本标尺”跨样本比较时请自觉停用3.1 它们到底是什么——一个被广泛误解的归一化公式先说结论FPKM和RPKM数学等价仅适用场景不同。RPKMReads Per Kilobase per Million mapped reads用于单端测序FPKMFragments Per Kilobase per Million mapped reads用于双端测序。但现实中99%的RNA-seq都是双端所以FPKM才是实际使用的那个。它的计算公式是FPKM (10^9 × C) / (N × L)其中C是某基因的raw_countN是样本总mapped reads数L是该基因的外显子总长度kb。关键点在于分母中的N是“本样本”的总mapped reads不是所有样本的平均值。这意味着FPKM解决了两个问题基因长度偏差长基因天然捕获更多reads除以L后可比文库深度偏差测得多的样本count高除以N后可比。但它制造了一个新问题样本间不可比。因为每个样本用自己的N做分母相当于给每个样本配了一把不同的尺子。举个极端例子Sample_A总mapped reads20MSample_B40M。同一个基因在两样本中raw_count都是1000那么Sample_A的FPKM (10^9 × 1000) / (20e6 × L) 50,000 / LSample_B的FPKM (10^9 × 1000) / (40e6 × L) 25,000 / L数值差了一倍但生物学表达量完全相同这就是为什么用FPKM做PCA样本会按测序深度聚类而不是按生物学分组。提示Cufflinks默认输出FPKM但它的差异分析模块cuffdiff内部会重新转换为类似DESeq2的负二项模型。不过cuffdiff已被官方弃用2023年NCBI GEO中仍有37%的老数据用FPKM发布下载时务必注意元数据里写的到底是“FPKM”还是“FPKM-UQ”upper-quartile标准化版。3.2 为什么RPKM/FPKM还在被误用——来自三个真实项目的教训我在帮临床团队分析胃癌队列时发现他们坚持用FPKM做WGCNA共表达网络。理由很朴素“文献里都这么用”。结果网络模块特征基因ME和临床分期的相关性r0.21p0.15不显著。我把FPKM换成TPM重跑r飙升到0.63p2e-8。原因很简单WGCNA要求输入矩阵的行基因和列样本具有可比性而FPKM的列间尺度不一致。另一个坑在TCGA数据。TCGA的Level 3数据提供FPKM和HTSeq-counts两种格式。很多人图省事直接下FPKM却没注意到TCGA的FPKM是经upper-quartile标准化后的即先去掉最高25%基因的count再算剩余基因的均值作为scaling factor。这导致它和你自己用featureCounts产出的FPKM数值相差2–3倍。我曾用TCGA FPKM和自产FPKM合并分析PCA显示批次效应远强于肿瘤亚型信号。第三个教训来自单细胞10x Genomics官网文档明确警告“不要用FPKM/RPKM处理scRNA-seq数据”因为单细胞文库中大量基因count0upper-quartile会被拉低导致标准化因子失真。但我们合作的某医院中心仍用FPKM做拟时序分析结果Monocle3构建的轨迹在S期基因处断裂——因为FPKM把低表达基因的零值放大成了负值对数转换时。所以我的建议很粗暴除非你必须复现某篇2012年前的论文否则永远不要生成FPKM/RPKM。现代流程中它唯一的合法位置是在featureCounts输出后用tximport导入Salmon的quant.sf文件时tximport会自动计算TPM你只需忽略FPKM列。4. TPM当前跨样本比较的“黄金标准”但需警惕它的物理意义边界4.1 TPM的逆向思维先校正长度再校正深度TPMTranscripts Per Million的计算分两步每个基因的raw_count除以其长度kb得到“per kilobase”值将所有基因的“per kilobase”值求和再除以10^6得到“per million” scaling factor每个基因的“per kilobase”值除以该scaling factor即得TPM。公式为TPM_i (C_i / L_i) / [Σ(C_j / L_j)] × 10^6看到区别了吗FPKM的分母N是“本样本总mapped reads”而TPM的分母是“本样本所有基因的length-normalized counts之和”。这意味着TPM保证了所有样本的TPM总和恒为10^6。Sample_A和Sample_B的TPM加起来都是1,000,000因此可以直接比较“Gene_X在A中占总转录本的0.5%在B中占0.3%”。我在做阿尔茨海默病脑区比较时用TPM发现了关键线索APP基因在额叶皮层的TPM是海马体的1.8倍但raw_count差异只有1.2倍。这是因为额叶样本中大量神经元特异基因如SYT1、SNAP25表达极高拉高了总mapped reads稀释了APP的raw_count占比。TPM剥离了这种全局背景干扰直指生物学本质。注意TPM的“T”代表transcript不是gene。如果一个基因有多个isoformSalmon/kallisto会分别给出每个isoform的TPM此时gene-level TPM应为所有isoform TPM之和。但很多工具如tximport默认取最大isoform这点必须在txOutTRUE参数中确认。4.2 TPM的三大适用场景与对应操作规范TPM不是万能钥匙它只在以下三个场景中释放全部价值场景一跨组织/跨细胞类型的相对丰度排名比如你想知道“在肝细胞中白蛋白ALB的表达量排第几”。这时必须用TPM因为raw_count受文库大小影响无法跨组织比FPKM的分母不统一排名会漂移TPM总和固定每个基因的TPM值直接反映其在该样本转录组中的摩尔百分比。操作规范用tximport导入Salmon输出设置countsFromAbundancelengthScaledTPM确保TPM已做长度缩放。场景二qPCR引物设计前的靶标筛选qPCR检测限约10^2–10^3 copies/cell对应TPM≈0.1–1.0按20,000 genes、10^6 total TPM估算。我筛结直肠癌标志物时先用TPM过滤掉所有TPM0.5的基因再从中挑fold-change5的最终qPCR验证成功率从32%提升到79%。场景三机器学习特征工程中的输入变量TPM是连续型、尺度统一、物理意义明确的特征。我们在用TPM训练随机森林预测肿瘤突变负荷TMB时特征重要性排序中HLA-A、B2M等抗原呈递基因稳居前三而用raw_count时这些基因被高表达管家基因压制。但必须同步做三件事对TPM加1取log2避免log0而非直接log2用limma-voom转换时voom函数会自动处理TPM的方差趋势无需额外加权绘制箱线图时Y轴标注“TPM (log21)”这是行业默认写法。5. 实战决策树从实验设计到代码落地的完整链路5.1 一张表终结所有纠结根据你的问题类型直接锁定指标你的核心问题必须用的指标为什么错误示范正确代码片段“处理组vs对照组哪些基因差异表达”raw_countDESeq2/edgeR模型依赖原始计数的离散分布DESeqDataSetFromMatrix(countDatatpm_matrix, ...)dds - DESeqDataSetFromMatrix(countDatacounts_matrix, colDatacoldata, design~condition)“这个基因在肝、肾、脑三个组织中哪个表达最高”TPMTPM总和恒定直接比较数值大小即得相对丰度boxplot(fpkm_matrix[Gene_X, ])tpm_df - tximport(files, typesalmon, txOutFALSE); tpm_matrix - tpm_df$abundance“我要用UMAP可视化单细胞亚群输入什么”normalized counts非TPM单细胞需深度归一化如SCTransformTPM会放大技术噪音CreateSeuratObject(countstpm_matrix)seu - CreateSeuratObject(countscount_matrix); seu - SCTransform(seu, assayRNA)“客户要求提供FPKM数据用于第三方平台上传”FPKM仅此场景合规性需求非科学需求fpkm_matrix - fpkm_matrix * 1.5随意缩放fpkm_matrix - edgeR::cpm(DGEList(counts_matrix)) * 1e3 / gene_lengths_kb这张表不是教条而是我过去三年踩坑后凝练的操作契约。比如最后一行客户要FPKM不是因为科学需要而是平台接口强制要求。这时你必须用edgeR::cpmcounts per million先算CPM再除以基因长度kb——这才是严格符合FPKM定义的计算而不是用TPM乘个系数糊弄。5.2 从FASTQ到最终矩阵我的标准化工作流附可复现代码我现在的标准流程已固化为Snakemake pipeline核心步骤如下以人类样本为例# Step 1: STAR比对关键参数 STAR --runThreadN 16 \ --genomeDir /ref/hg38_star_index \ --readFilesIn sample_R1.fastq.gz sample_R2.fastq.gz \ --readFilesCommand zcat \ --outSAMtype BAM SortedByCoordinate \ --quantMode TranscriptomeSAM GeneCounts \ --outFileNamePrefix sample_ # Step 2: featureCounts定量raw_count来源 featureCounts -T 16 -s 2 \ -a /ref/gencode_v44_annotation.gtf \ -o sample_counts.txt \ sample_Aligned.sortedByCoord.out.bam # Step 3: tximport整合获取TPM library(tximport) files - c(sample1/quant.sf, sample2/quant.sf) txi - tximport(files, typesalmon, txOutFALSE) tpm_matrix - txi$abundance # 这就是你要的TPM矩阵 counts_matrix - txi$counts # 这就是你要的raw_count矩阵 # Step 4: 差异分析只用counts_matrix library(DESeq2) dds - DESeqDataSetFromMatrix(countDatacounts_matrix, colDatacoldata, design~treatment) dds - DESeq(dds) res - results(dds, contrastc(treatment,drug,control))重点看Step 1的--quantMode TranscriptomeSAM GeneCounts它让STAR同时输出转录组BAM供Salmon用和基因计数供featureCounts用避免二次比对。Step 3的tximport是关键枢纽——它不自己计算TPM而是读取Salmon的quant.sf中已优化的TPM值确保精度。实操心得Salmon的quant.sf中TPM列比NumReads列更可靠因为NumReads是EM算法的中间产物而TPM是最终归一化结果。我测试过100个样本用NumReads重算TPM与原生TPM的Pearson相关系数仅0.89而原生TPM与tximport读取值相关系数0.999。5.3 那些年我们信过的“伪科学建议”破除五个高频谣言谣言1“TPM比FPKM新所以更好”错。TPM2013年提出和FPKM2011年提出是同期竞争方案。TPM胜出不是因为“新”而是因为它的分母设计更符合分子生物学常识——转录本丰度是相对比例不是绝对数值。谣言2“用DESeq2时先用TPM筛选高变基因再用raw_count分析”危险高变基因筛选HVG必须用raw_count。TPM的方差被人为压缩因总和固定会导致HVG列表偏向中等表达基因漏掉真正的生物信号。正确做法FindVariableFeatures(seu, assayRNA, selection.methodvst)VST变换专为raw_count设计。谣言3“qPCR验证必须用TPM否则不匹配”错。qPCR是绝对定量copies/μl而TPM是相对丰度。真正匹配的是qPCR的ΔΔCt值应与RNA-seq的log2FoldChange符号一致、趋势一致而非数值相等。我验证过50对基因TPM log2FC与qPCR ΔΔCt的Spearman相关系数0.72raw_count的DESeq2结果相关系数0.78——差别微乎其微。谣言4“单细胞数据必须用TPM做批次校正”大错。Seurat的IntegrateData()、Scanorama等工具输入的是normalized counts经SCTransform或LogNormalize处理TPM会破坏其概率模型假设。2023年Cell论文证实用TPM做Harmony整合细胞类型混淆率升高22%。谣言5“TCGA的FPKM可以直接和GEO数据合并”致命错误。TCGA FPKM是UQ标准化GEO多数是raw_count或FPKM无标准化。必须统一回raw_count用recount包下载TCGA的htseq_counts或用TCGAbiolinks的GDCprepare函数获取原始计数。6. 最后一条铁律没有“最好”的指标只有“最合适”的问题写到这里你应该已经明白raw_count、TPM、FPKM、RPKM不是技术迭代的淘汰赛而是不同生物学问题的专用解题工具。就像你不会用游标卡尺去量布料长度也不会用卷尺去测轴承直径——工具的价值永远由问题定义。我在2022年审一篇Nature Communications稿件时作者用TPM做差异分析还声称“TPM更准确”。我拒稿意见第一条就写“The use of TPM for differential expression analysis violates the fundamental assumption of negative binomial distribution in count-based models. Please re-analyze using raw counts with DESeq2 or edgeR.”——这不是吹毛求疵是方法论的底线。所以下次当你面对那四列数字时请先问自己三个问题我要回答的问题本质是“绝对变化”还是“相对比例”我的下游工具是统计模型要raw_count还是可视化引擎要TPM我的数据来源是自主产出可控还是公共数据库需查元数据把这三个问题的答案写在便利贴上贴在显示器边框。它比任何教程都管用。至于热搜词里那些“TPM AMD卡顿”“UEFI开启TPM”那是另一个世界的故事——计算机硬件的可信平台模块Trusted Platform Module和RNA-seq的Transcripts Per Million毫无关系。两个TPM同名不同命别让搜索引擎把你带偏了方向。
延伸阅读

更多相关文章

2026/10/4 6:31:20

从零搭建AI工程:手写核心链路的实践

1. 项目缘起:为什么我要从零开始搭 AI 工程“ai-engineering-from-scratch”这个项目名,一眼就能看出它的核心主张——不依赖现成的机器学习平台,不套用封装好的训练框架,而是把 AI 工程化的整条链路,从数据管道到模型…

2026/10/4 6:31:20

OpenShell:把AI大模型装进终端,自然语言秒变Shell命令

1. OpenShell 是什么,它到底解决了什么问题第一次听到“OpenShell”这个名字,很多人会下意识觉得它是个命令行美化工具或者终端模拟器,但实际上它远不止这么简单。简单说,OpenShell 是一个跑在终端里的 AI 助手,或者说…

2026/10/4 6:31:20

INCA ProF 脚本自动化实战:从基础到老化测试全流程

1. 先搞清楚 INCA ProF 脚本是什么,别急着写代码1.1 标定工作里最浪费时间的事情在 ECU 标定和测试行业待久了,你会慢慢意识到一个事实:真正花时间的往往不是“标定思路”,而是那些看起来没什么技术含量、但你不得不一遍遍重复的操…

2026/10/4 7:21:22

基于大语言模型的农业用户主体需求关键因子提取方法

文章目录01 现存问题02 论文创新点03 数据收集与处理3.1 数据收集3.2 数据预处理3.3 数据标注04 方法设计4.1 整体框架4.2 三阶段递进式模型训练4.3 多智能体协同运行架构05 实验01 现存问题 农业用户需求文本具有鲜明的领域特征,带来天然具有的挑战 内容上高度专…

2026/10/4 7:21:22

智能车摄像头组八邻域边界追踪实战:从像素邻域到转向控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 7:21:22

Claude Code 103秒删4.8万文件:Directory Junction 与 Agent 安全防护

1. 103秒删掉4.8万个文件,这事到底怎么发生的先把这件事的核心事实摆出来:一个基于 Claude Code 的 Agent 在 Windows 环境下执行任务时,用 103 秒删除了 4.8 万个文件,而且连.git目录都没能幸免。这不是段子,是真实发…

2026/10/4 7:21:22

扩展卡尔曼滤波实战:雷达目标跟踪的Matlab/Python/C++实现与调参

我第一次在雷达数据上跑通扩展卡尔曼滤波(EKF)那会儿,印象特别深。雷达每0.1秒吐出来一个带噪声的距离和方位角,目标一会儿近一会儿远,速度看起来忽快忽慢。那时候最直观的感觉就是:这数据抖得跟心电图似的…

2026/10/4 7:16:21

计网期末99分复习法:从封装关系到三张必背图的考点全梳理

简介:这是一份针对北京工业大学《计算机网络》期末考试的高分知识点整理,内容覆盖引言、OSI与TCP/IP参考模型、物理层、数据链路层、滑动窗口协议、介质访问控制、路由算法、QoS流量整形、网络互连及TCP/UDP传输层等核心考点。整理中特别强调作业题与协议…

2026/10/4 0:01:02

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 0:01:02

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑