简介:这份获奖公开课课件面向生物信息学入门者与科研人员,系统梳理常用生物数据库与常见数据格式,帮助读者快速建立检索与解析生物数据的知识框架。课件共1个pptx文件,压缩包约9.49MB,内容涵盖FASTA、FASTQ、GFF、GenBank、EMBL等核心格式的结构与用途,并重点讲解NCBI、EBI、DDBJ三大核酸序列数据库,以及Gene Ontology、KEGG、InterPro等基因功能数据库,同时介绍UCSC Genome Browser与Ensembl等基因组浏览与注释工具。每类数据库均配有典型记录示例,例如GenBank文件的LOCUS、FEATURES、ORIGIN等段落解读,便于对照学习。目前已有90人学习浏览,适合用作生信课程教学参考或自学入门材料,也可帮助研究者快速定位所需数据库并理解相应数据格式规范。
1. 生物数据库与数据格式:入门第一课也是最容易翻车的一课
很多做生信的同学入行第一步不是跑模型、不是装软件,而是在"去哪下载数据、下载什么格式、拿到手怎么处理"这三件事上反复折腾。某课题组有同学从测序公司拿回一个 .sam 文件,想都不想就导入只支持 BAM 的分析软件,报错五分钟没找到原因。公开课里常把这部分内容做成"常用生物数据库和数据格式"课件,把数据库选型和格式概念讲得很清楚,但真正的难点在转换和排错。我把这套知识整理成一份可直接复现的实操路径,覆盖数据库选型、格式解析、转换命令和最容易踩的坑,新手照着走一遍就能把原始数据整理成可分析状态,熟手也能在这些细节里找到自己当初没注意的边界。
2. 常用生物数据库选型:先搞清楚去哪查,再谈怎么查
2.1 主流核酸与基因组数据库的分工
生物数据库数量庞大,但日常分析高频用到的不超过十几个。核酸序列层面大家最早接触的是 GenBank,它收录了全球研究者直接提交的原始序列,记录详细但存在冗余,同一个基因可能有几十条几乎一样的记录。做比对搜索时这种冗余会影响结果排序,所以日常做基因注释或基因预测时更多用 RefSeq,它把序列做了合并与去重,每条记录有稳定的 accession 版本号,比如 NM_ 开头的转录本、NP_ 开头的蛋白质,版本变化一眼可查。某图像处理 Demo 的序列比对模块里测试过,用 RefSeq 做注释比对,命中的稳定性明显高于直接用 GenBank 原始提交。
Ensembl 和 UCSC 是两条主流基因组浏览器路线,提供染色体级别的基因组组装序列和全套注释文件。两者在注释版本命名上不同:Ensembl 用 release 编号,物种按 assembly 版本区分,比如人类 GRCh38;UCSC 则用 genome build 代号,同样对应 GRCh38 时又叫 hg38。实际工作中同一个基因组在两个平台下载的 GTF 注释文件,基因 ID 前缀会不一样,Ensembl 是 ENSG 开头,UCSC 的某些 track 会直接给已知基因符号。做跨平台整合时,这些映射关系必须在最开始统一,否则后期合并样本批次会花大量时间在 ID 转换上。
用一张表总结三个主数据库的定位差异比较直观:
| 数据库 | 核心定位 | 更新节奏 | 应用边界 |
|---|---|---|---|
| GenBank | 原始序列收录 | 持续接收提交 | 检索原始记录、变异来源追溯 |
| RefSeq | 去冗余参考序列 | 版本化更新 | 基因结构注释、转录本分析 |
| Ensembl / UCSC | 基因组组装与注释整合 | 定期发布 release | 比较基因组、注释提取、浏览器可视化 |
选型原则一句话:需要"最新最全"去 GenBank,需要"稳定可复现"去 RefSeq,需要"配套注释与功能 track"去 Ensembl 或 UCSC。三者之间没有谁完全替代谁,很多流程里会用 Ensembl 的 GTF 做基因结构注释,用 RefSeq 做转录本 ID 标准化,再拿 UCSC 的保守性 track 做过滤,这种组合很常见。另一个高频需求是比对搜索,NCBI 的常用做法是把序列输入比对接口,但接口有返回条数限制,大规模全基因组比对建议下载本地数据库再跑,后面第 4 章会展开。
2.2 蛋白质、通路与变异数据库怎么选
蛋白质序列和功能注释层面,UniProt 是绕不开的。它由 Swiss-Prot(人工审核)、TrEMBL(自动注释)和 PIR 整合而成。做检索时优先用 Swiss-Prot,每条记录都有功能、结构域、翻译后修饰的注释支持,可信度高;需要对大规模蛋白组做快速注释时再用 TrEMBL。PDB 则专门沉淀三维结构数据,做结构比对、分子对接时用得上,它和 UniProt 之间有交叉引用,从 UniProt 的蛋白质记录里可以直接跳到 PDB 结构,命名空间不是隔离的。
变异与临床关系是另一个高频查询方向。dbSNP 收录单核苷酸变异和插入缺失等小规模变异,ClinVar 在 dbSNP 基础上加上了临床意义评级,比如致病性、良性、意义未明。做肿瘤样本分析时还会用到体细胞变异方向的专门资源,它们把 COSMIC、TCGA 这些公开资源的变异注释汇总成可直接检索的形式。功能通路方向主要是 KEGG 和 Gene Ontology(GO),KEGG 给的是代谢通路和信号通路的基因集合,GO 给的是基因在不同生物学过程、分子功能和细胞组分的分类标签。
选型上的常见纠结点在 KEGG 和 GO 之间:KEGG 强调"通路"这个整体视角,适合做差异基因的基因集富集分析,看某个通路整体有没有被激活;GO 强调"标签"这个维度,适合描述某个基因或某组基因在功能层面的分布。两者不是竞争关系,很多课题里既要 KEGG 富集结果也要 GO 富集结果,分别回答系统级和模块级的问题。蛋白层面还有一个常被忽略的点:做跨物种注释时优先用直系同源编号做映射,不要直接用基因符号,因为不同物种里同一个符号可能对应不同蛋白。
2.3 命令行检索与批量下载的常用做法
网页检索适合单条查询,数据分析脚本需要的是批量、可重复的下载方式。常见做法是用各数据库提供的 FTP 或专用下载接口,把文件拉进本地统一管理。以 Ensembl 为例,从 release 页面拿到物种目录路径后,用 wget 或 curl 完整拉取注释和序列。写一个最小下载脚本:
#!/bin/bash # 从Ensembl指定release下载人类GTF注释文件 ENSEMBL_RELEASE=110 SPECIES=homosapiens BASE_URL="https://ftp.ensembl.org/pub/release-${ENSEMBL_RELEASE}/gtf/${SPECIES}/" FILE="Homo_sapiens.GRCh38.${ENSEMBL_RELEASE}.gtf.gz" wget -c -t 5 -O "${FILE}" "${BASE_URL}${FILE}" # 下载完成后立即检查文件大小,不完整就删除重试 if [ -f "${FILE}" ]; then ls -l "${FILE}" fi这里-c支持断点续传,网络中断后重跑不会从头再来;-t 5指定最多重试五次,避免偶发网络抖动导致下载直接失败。-O把文件固定命名,方便脚本后续直接引用,不会因为 URL 里带版本号导致文件名多几个数字就对不上。NCBI 方面对应的是 datasets 命令行工具,提供统一下载入口,可以把基因序列、注释和统计报告打包下载,还可以只挑特定基因区间而不是整个基因组。以基因名列表批量拉取序列为例:
# 按gene_id列表批量下载FASTA序列 datasets download gene gene-id --inputfile gene_ids.txt \ --include genomic,protein --filename genomes.zip unzip genomes.zip -d datasets_dir这条命令的--include参数决定拿哪些内容,常见取值有genomic(基因组长序列)、protein(蛋白序列)和rna(转录本序列),按需选而不是全量拉取,否则一个打包文件里塞进大量用不到的内容。--inputfile接受一个每行一个 ID 的文本文件,适合上游流程直接输出 ID 列表的情况。注意下载下来是一个 zip 包,要先解压再交给下一步分析,很多新手直接在 zip 上做文件扫描导致路径全部落空,这在第 5 章会细说。
3. 核心数据格式逐一生理解析:FASTA、FASTQ、GTF、VCF 与 SAM/BAM
3.1 FASTA 与 FASTQ:序列和质量的两种表达
FASTA 是生物信息学最基本的序列格式,一条记录由两行组成:以>开头的标题行描述序列 ID 和注释信息,紧接着一到多行的序列字符串。它的核心设计是"自由断行",即序列可以在任意位置换行,解析时需要把多行序列拼成一条。这也带来了最常见的坑:按行读取时把中途断行的序列当成了多条记录,或者统计序列长度时只算了第一行。
# 正确解析FASTA:把连续序列行拼接为一条完整序列 def parse_fasta(filepath): records = {} # 使用字典存储,避免列表去重问题 current_id = None with open(filepath) as fh: for line in fh: line = line.strip() if not line: continue if line.startswith(">"): current_id = line[1:].split()[0] # 取首个字段作为唯一标识 records[current_id] = [] elif current_id is not None: records[current_id].append(line) # 将列表拼接成字符串,这才是完整序列 result = {k: "".join(v) for k, v in records.items()} return result这个解析函数的关键逻辑是:遇到>就切换当前记录 ID,普通行则追加到当前 ID 对应的列表,到末尾再把列表 join 回完整序列。如果漏掉 join 这一步直接统计每个 ID 对应列表长度,得到的会是"序列断行次数"而不是"序列长度",这就是实打实的血泪经验。另一个细节是标题行按空格分割取第一个字段作为 ID,因为很多 FASTA 标题里带有额外注释,不全取则可能把空格后面的描述也带进 ID,造成下游匹配失败。
FASTQ 在 FASTA 基础上增加了质量信息,每条记录固定四行:以@开头的 ID 行、序列行、以+开头的分隔行(通常只写+,有时会重复 ID)、质量值行。质量值的编码方式有 Phred+33 和 Phred+64 两代,两者在 ASCII 字符偏移上不同。判断依据很简单:Phred+33 的字符范围是!到~,Phred+64 的范围是@到h附近。测序仪下机数据大多已经是 Phred+33,但个别老格式或某些平台转换工具会输出 Phred+64,质量值不经转换直接进分析流程,会导致碱基质量系统性偏低或偏高,最终影响变异检测的敏感度。
3.2 GTF/GFF 与 BED:注释和区间的坐标差异
GTF 和 GFF 是基因注释文件的主流格式,按行描述一个基因特征。GTF 是 GFF2 的衍生变体,核心是九个制表符分隔的列:seqid、source、type、start、end、score、strand、frame、attributes。attributes 里用键值对描述基因 ID、转录本 ID、基因名等信息,是目前做 RNA-seq 定量时使用最广泛的注释载体。GFF3 则是 GFF2 的重新设计,在第九列里改用ID=和Parent=来建立特征之间的层级关系,比如一个转录本(type 为 mRNA)的 ID 是transcript:abc,它的外显子(type 为 exon)通过这些 ID 挂到这个转录本下。
GTF 里的transcript_id和gene_id在主属性里直接给,GFF3 则不一定,有些文件把基因 ID 放在 Parent 属性而不是自身 ID 里。做转换脚本时如果把 GFF3 当 GTF 去解析第九列,拿不到gene_id键就会报 KeyError。这个问题我在某跨平台系统的数据整合环节排查过,最后发现是文件格式版本判断错了,GFF3 和 GTF 远比想象中更不兼容,写解析器前一定要先看文件头注释或者前几行特征类型。
BED 用于描述染色体区间,最简单的 3 列是 chrom、chromStart、chromEnd,注意这里的坐标是 0-based 半开区间:起始坐标从 0 开始计数,end 是"不包含"的右边界。GTF 和 GFF 是 1-based 闭区间:起始坐标从 1 开始计数,end 是包含的右边界。同样一段位于第 100 到第 200 个碱基的区域,在 GTF 里写100 200,在 BED 里必须写成99 200,如果只是把 GTF 的 start 减一、end 不变,就会把所有区间向右整体偏移一个碱基,做变异位点匹配时全部错位。坐标转换的代码看起来很机械,但值得每次都在新数据集上验证一次。
# GTF转BED的常见做法:取特征为exon的行,转换坐标 awk 'BEGIN{OFS="\t"} $3=="exon" { # GTF的start是1-based闭区间,BED是0-based半开区间 # 先转换为染色体名、start-1、end的三列BED,再补上基因ID作为第四列 gene_id = "" for (i = 9; i <= NF; i++) { if ($i ~ /^gene_id/) { gsub(/[";]/, "", $i) gene_id = $i } } print $1, $2 - 1, $3, gene_id }' input.gtf > output.bed这里的BEGIN{OFS="\t"}设定输出分隔符为制表符,避免默认空格导致 BED 解析失败。$3=="exon"只抽取外显子行,这是 BED 分析中最常见的注释转区间场景。第九列解析时用正则去掉引号和分号,取到干净的 gene_id。转换后建议用sort -k1,1 -k2,2n排序再交给 bedtools,因为很多区间分析工具要求输入文件先按染色体和起始位置排序,未排序的 BED 会导致交集结果少掉一半。
3.3 VCF 与 SAM/BAM:变异和比对的字段结构
VCF 是变异检测结果的标准格式,文件开头用##注释行记录参考基因组版本、样本名称和过滤阈值,再以#CHROM表头行开始正式的八列固定字段:CHROM、POS、ID、REF、ALT、QUAL、FILTER、INFO,之后每增加一个样本就追加一列样本级的 GT 和 DP 等信息。POS 在 VCF 里是 1-based 的,和 GTF 一致,这一点和 BED 完全相反,很多从 BED 思维切到 VCF 的人会在这里翻车。FILTER 列是变异可信度的重要关卡:PASS 表示通过了所有过滤条件,如果显示q10、s50这样的标签,说明有相应的质量或样本深度指标没达标。
做下游分析时不建议直接删掉非 PASS 位点,更稳妥的做法是保留它们但单独标记,因为某些低频分析和拷贝数分析里,非 PASS 位点可能恰恰代表了真实存在的信号。REF 和 ALT 字段描述的是参考碱基和变异碱基,做多样本联合分析时要注意 ALT 可能包含多个等位基因,用逗号分隔,解析时要按逗号拆开而不是当成整体判断。SAM 和 BAM 是序列比对文件的一对孪生格式:SAM 是文本,BAM 是二进制压缩版,不能直接看,必须用 samtools 转换后查看。
SAM 的核心分成文件头(@HD、@SQ、@RG等)和比对记录行。每条比对记录至少 11 个字段,其中 RNAME 代表参考序列名、POS 代表比对起始位置、MAPQ 代表比对质量、CIGAR 代表比对操作的描述串。CIGAR 里的 M、I、D、N 各自含义不同:M 是匹配或错配,I 是在读段上多出来的插入,D 是在参考基因组上缺失的缺失,N 则是跨越内含子的剪接区域。做 RNA-seq 数据分析时如果不理解N的含义,会把跨越内含子的比对误认为大片段缺失,进而在变异检测阶段产生一大串假阳性。
# 常用samtools命令:排序并对BAM建索引 samtools sort -@ 4 -o sample.sorted.bam sample.bam samtools index sample.sorted.bam-@ 4指用 4 个线程跑排序,数据量不大时开太多线程反而因为 IO 瓶颈变慢,一般按机器核数的一半设置即可。-o指定输出文件名,排序后的 BAM 才能被 index 建立索引,很多分析工具要求同时输入 BAM 和 BAI 文件,索引缺失直接报错。这里我一般会顺手跑一条samtools flagstat看一下比对统计,确认比对率正常再进下游,比对率过低说明参考基因组选错了或者样本本身有问题,这个习惯能省掉后面一整轮的排错。
4. 格式转换与数据清洗实操:从原始下载到可分析状态
4.1 用 seqkit 做序列格式清洗与统计
seqkit 是处理 FASTA/FASTQ 的常用工具,功能覆盖格式转换、序列统计、过滤、抽样和去冗余。新下载的序列文件建议先做一次统计体检,确认序列条数、总长度、GC 含量和 N 碱基比例在合理范围内,再进入后续分析。最小统计命令:
# 统计FASTQ文件的基本指标 seqkit stats sample_R1.fastq.gz # 输出格式为file、num_seqs、sum_len、min_len、avg_len、max_len、GC%拿到统计结果后先看 num_seqs 和老实验记录中的预期条数是否一致,比如上机时写了 5000 万条 read,结果只有 4800 万,可能是在质控阶段被过度过滤;再看 avg_len 和 GC%,如果 GC% 和该物种的已知基因组组成差异过大,要怀疑是不是测序样本被污染或混入了其他来源的核酸。seqkit 的 stats 命令不会修改文件,是零风险的健康检查,每次拿到新数据先跑一遍,比直接进分析流程稳得多。
格式转换是另一个高频需求。从 FASTQ 提取 FASTA、做反向互补、从 BAM 比对结果还原 FASTQ,常见操作都能用 seqkit 完成。以截取 FASTA 序列的指定区间为例:
# 按坐标提取FASTA子序列,窗口来自一个BED文件 seqkit subseq --bed regions.bed genome.fa > extracted.fa--bed参数直接接受 BED 文件作为区间输入,省去手工写坐标的步骤。注意--bed模式下坐标按 BED 规则解析(0-based 半开),所以待提取区间在 BED 里写100 200,输出的是参考序列上第 101 到 200 位,与 BED 语义一致。如果你习惯 GTF 的 1-based 坐标,需要把所有起始坐标减一后再写入 BED,否则会系统性偏移一位。转过一次之后建议拿一个已知基因的坐标做验证,在浏览器里确认提取出来的是目标区域,不要直接信任脚本输出。
4.2 用 samtools 处理比对文件:排序、建索引与转换
samtools 是对 SAM/BAM/CRAM 全生命周期操作的核心工具。拿到一个原始 SAM 文件,常见的第一条命令是转换成 BAM 并排序:
# SAM转BAM并排序,这里的sample.sam是上游比对软件直接输出的文件 samtools view -bS sample.sam > sample.bam samtools sort sample.bam -o sample.sorted.bam samtools index sample.sorted.bam # 查看比对率和比对质量分布 samtools flagstat sample.sorted.bam-b表示输出 BAM 格式,-S表示输入是 SAM 格式,这两个参数在旧脚本里经常被省略导致格式判断错误。排序是在比对结束后必须做的步骤,因为上游比对软件输出的顺序是按 readname 或并行分片的顺序排的,不是按基因组坐标排的,很多下游工具(比如变异检测和可视化)强制要求坐标排序。flagstat输出的mapped占比如果低于 80%,先检查参考基因组版本和样本物种是否匹配,不要急着调参数,物种不匹配时比对率低是必然结果,调参数也救不回来。
特定区间提取是 samtools 的另一核心能力,适合从全基因组 BAM 中提取某个目标区域的比对信息:
# 提取chr1:100000-200000区间的比对,输出为新的BAM samtools view -b sample.sorted.bam chr1:100000-200000 > target_region.bam samtools index target_region.bam这里区间写法同样是 0-based 半开,所以chr1:100000-200000实际包含的是第 100000 到 200000 个碱基的位置,与 BED 语义一致。注意必须用排序后的 BAM 才能做区间提取,未排序文件直接按坐标提取会把分散在文件各处的比对全部漏掉。提取后的子 BAM 仍需要单独建索引,某些工具会报 missing index 错误,原因往往就在这里,重新 index 一下就能解决。
4.3 用 bedtools 完成区间操作与注释文件转换
bedtools 家族是区间分析的主力。intersect 可以找两个区间文件的重叠部分,subtract 可以剔除特定区域,merge 可以合并相邻区间。以根据 BED 区间统计 FASTA 文件的 GC 含量为例:
# 计算每个BED区间的GC含量,输出每行一个区间的统计结果 bedtools nuc -fi genome.fa -bed regions.bed > region_gc.txtnuc子命令逐区间扫描参考序列给出碱基组成和 GC 含量,输出是一个 TSV 文件,可以直接做后续可视化。它的前提是 BED 的染色体命名和 FASTA 里的染色体命名完全一致,如果 FASTA 用的是chr1而 BED 用的是1,会直接返回 0 条记录且不报错,这是非常隐蔽的数据丢失。拿到输出后先看一眼行数是否等于 BED 的区间数,对不上就一定有问题。
注释转换也常落到 bedtools 或同类工具上。例如把 Ensembl 的 GTF 注释转为基因区间的 BED,更常规的做法是先用解析工具提取信息,再喂给 bedtools 做区间运算。下面是用 gffread 把 GTF 转为标准化版本的做法:
# 将GTF转为gene-level的注释表,gffread会检查特征父子关系 gffread input.gtf -T -o output.gtf # 然后可以再用awk提取exon区间转成BED,供bedtools使用 awk '$3=="exon"' output.gtf | \ awk 'BEGIN{OFS="\t"}{print $1, $4-1, $5, $9}' | \ sed 's/;.*//' > exons.bedgffread在转出时会检查特征的父子层级关系,缺失 Parent 关系的记录会被丢弃。如果你的 GTF 来自非标准来源,转换后务必统计一下转录本数量是否明显减少,减少幅度超过 5% 时要回看原始文件里的 type 字段和 attributes 字段是否写全。转换和提取这两步分开做,比用一条超长管道更容易排查问题,中间文件留在磁盘上,出错了能定位到具体环节。
5. 数据下载与格式解析的常见问题与排查:现象、原因与解决办法
5.1 下载的压缩文件解压后校验失败
现象:从数据库 FTP 下载的.gtf.gz文件,用gzip -t校验时报错,解压出来的 GTF 里中间一大段缺失,分析脚本运行到一半就报错,甚至不报错只是后续注释结果少了很多基因。
原因:下载过程中网络中断,wget 或 curl 没有加断点续传参数,文件只写了一半就结束。更隐蔽的情况是服务器端的文件本身在维护中,下载到了临时占位文件,或者通过浏览器下载时自动重命名了后缀。
解决:下载命令一律加-c断点续传参数;下载完成后先跑gzip -t file.gz再解压,不要跳过校验。对于大文件,最可靠的做法是在服务器上先获取文件的 MD5 校验值,下载后本地计算 MD5 比对,不一致就直接删除重来。另一个习惯是把下载脚本写成可重跑的形式,中断后直接重新执行脚本,而不是手动拼接文件。我在某跨平台系统的数据准备阶段就因为这个踩过坑,后来所有下载流程都强制加校验步骤,再没出过静默损坏的问题。
5.2 FASTA 序列里混进意料之外的字符
现象:用自己写的解析脚本读 NCBI 下载的 FASTA,统计长度时发现某条序列长度异常,或比对软件报非法字符错误,日志里出现invalid character之类的提示。
原因:序列文件里混入了非标准碱基字符,如U(RNA 序列)、I(肌苷),或者因为换行符问题导致序列行和标题行粘在一起。又或者在 Windows 环境下用记事本编辑过文件,加入了\r回车符,Linux 解析工具把\r当成序列字符处理,序列长度和比对结果全部偏移。
解决:用seqkit clean处理非法字符,把非 ACGTN 字符统一替换或剔除:
# 剔除非法字符:U转为T,I和R替换为N seqkit clean raw.fa -u S -u I -u R -n -a > clean.fa-u S把 U 替换为 T,-u I把 I 替换为 N,-u R把其他非标准字符替换为 N。在解析脚本里加白名单过滤也是一条路线,但 seqkit 一句命令更省事。还有一点容易被忽略:判断 FASTA 是否完整的最快方法是统计>开头的行数,和预期记录条数比对,差一条都别硬着头皮往下分析,序列缺失往往发生在文件拼接环节而不是源头。
5.3 坐标系统的混乱:BED 和 GTF 从不同程序读出来结果不一致
现象:同样的区间,在可视化工具里看是某个外显子,但脚本计算时偏移了一个碱基;或者两个软件对同一个位点的注释结果不一致,交集分析总是差几个碱基。
原因:BED 是 0-based 半开,GTF/GFF 和 VCF 是 1-based 闭区间。某些工具在内部做了坐标转换,文档里没写清楚;某些工具默认输入是 BED 但用户传了 GTF 风格的坐标,程序不报错只是结果全错。这是最危险的错误类型,没有异常提示,只有结果对不上。
解决:在脚本的注释和日志里明确标注坐标系统。我一般会在生成的中间文件命名里加上_0based或_1based后缀,防止后期混淆。跨工具比较时,先用一个已知坐标的位点做验证,比如取某条染色体上某个已知基因的第一个外显子,在可视化工具里目测确认坐标一致后再批量处理。
提示:BED 转 GTF 时,GTF 的起始坐标要在 BED 起始坐标基础上加 1,结束坐标不变;反过来 GTF 转 BED 时,起始坐标减 1。记不住就强制自己在代码里加注释,别靠一次性的临时记忆,两周后回头再看脚本,坐标系混乱的代码根本没法维护。
5.4 Excel 打开 VCF 后染色体编号变成日期
现象:用 Excel 直接打开 VCF 文件,CHROM列里的1、2这些染色体编号变成了1月、2月之类的日期格式,后续筛选全部错乱,而且保存后再用分析工具读取直接报错。
原因:Excel 的自动格式识别把纯数字列当成了日期,这是 Excel 的默认行为,不是 VCF 文件的问题。保存时 Excel 还会改写字段分隔符和换行符,导致文件在 Linux 端解析失败,比日期错乱更隐蔽的是编码变化。
解决:VCF 是纯文本,不要用 Excel 直接编辑。在命令行用less查看,在 Python 里用专门的解析库读取。如果一定要用表格软件查看,先把文件后缀改为.txt再打开,或者用支持制表符分隔的编辑器打开,能躲开自动格式转换。同样的问题也出现在基因名被 Excel 当成科学计数法的情况,某些基因 ID 包含字母 E,会被转成7.23E+12这样的格式,做变异注释时这种错误风险很高,处理前一定要检查有没有被表格软件动过。
注意:不要用 Excel 保存任何 VCF、GTF、FASTA 文件。保存行为本身会改变编码和换行符,中文 Windows 的 Excel 还会在文件头加 BOM,导致 Linux 端解析第一个字段时多出不可见字符。所有注释文件和变异文件只在命令行环境里处理,这是底线。
5.5 BAM 文件 index 报错:排序与比对标记不一致
现象:samtools index报错,提示索引文件不存在或索引无效;某些工具运行时报BAM index is not valid,或者读取 BAM 时提示truncated file。
原因:BAM 文件没有先排序就尝试建索引;或者文件在传输过程中损坏,没有完整落地;又或者用旧版本的 samtools 处理新版本工具生成的 BAM,索引格式互不兼容。还有一种情况是直接从比对软件拿到未排序 BAM,自己没跑排序就交给下游工具,工具内部尝试建索引失败。
解决:统一用samtools sort排序后再samtools index,不要把比对软件直接输出的未排序 BAM 拿来建索引。出现索引失效时,删除旧的.bai文件重新生成一次,不要在原索引上覆盖。如果 BAM 来自别人传递的中间文件,先用samtools quickcheck做一次体检:
# 检查BAM是否能被完整读取,输出ok表示正常 samtools quickcheck -v sample.sorted.bam && echo "ok" || echo "fail"-v参数让 quickcheck 输出详细错误信息,不只是退出码。体检通过后再建索引和跑下游。数据量特别大的 BAM 建议顺手记录一下samtools view -c的比对条数,和上游报告的条数对得上再继续,比等到分析结束才发现数据缺失要省事得多。
6. 把数据获取做成一键脚本:文件校验、版本记录与流程自动化
数据下载和格式整理这个环节,最大风险来自"人走茶凉"——实验记录里写着用的是某个数据库 release,但没人记得具体是哪个版本,几个月后想复现分析都无从下手。我一般会在每个项目目录下放一个MANIFEST文件,记录所有输入数据的来源 URL、下载时间、文件 MD5 和分析环境版本,内容类似:
# MANIFEST 示例:记录数据来源与校验信息 # 每个文件一行,用 >>>> 分隔字段,便于grep检索 file=/data/raw/Homo_sapiens.GRCh38.110.gtf.gz url=https://ftp.ensembl.org/pub/release-110/gtf/homosapiens/ md5=7c6a4c315a3c2d0e2a018f0ea1ede8de downloaded_at=2025-11-08 validator=samtools-1.17这个文件不是摆设。半年内要重跑分析、或者项目组另一个同学接手继续做时,能直接靠着 MANIFEST 把整个数据环境复现出来,而不需要翻聊天记录、找邮件附件。写校验脚本时,我会把md5sum -c的比对结果作为流程的强制前置步骤,校验失败就立即终止,不带着可能损坏的输入往下跑。
自动化流程的接入点,我习惯把下载和转换整合进一个 Makefile,让构建系统自动判断哪些步骤需要重跑:
# Makefile:一键完成下载、校验、格式转换 ENSEMBL_URL := https://ftp.ensembl.org/pub/release-110/gtf/homosapiens/Homo_sapiens.GRCh38.110.gtf.gz RAW_GTF := Homo_sapiens.GRCh38.110.gtf.gz BED_FILE := genes.bed $(RAW_GTF): wget -c -t 5 -O $@ $(ENSEMBL_URL) $(BED_FILE): $(RAW_GTF) gzip -dc $< | awk '$$3=="gene"{split($$9,a,";");gsub(/gene_id |"/,"",a[1]);print $$1,$$4-1,$$5,a[1]}' | tr ' ' '\t' > $@ manifest: $(BED_FILE) md5sum $(RAW_GTF) $(BED_FILE) > MANIFEST.md5 all: manifestMakefile 的好处在于把"文件是否已存在"和"输入是否已更新"交给构建系统判断,而不需要写一长串条件判断的 bash 脚本。依赖关系写清楚后,跑make all就能从原始下载一路做到 BED 文件生成,中间任何一步失败会停在出错的规则上而不是继续往下跑。awk 里把$9里的gene_id "xxx"清洗成xxx,输出的第四列就是干净的基因 ID,可以直接交给下游做区间统计。
最后把话收在一个习惯上:数据格式整理的功夫不在工具而在习惯。工具命令都能查到,真正让分析流程稳定的,是每次下载后顺手校验、每个转换文件标记坐标系统、每个项目留下版本记录。这三个习惯我踩了好几次坑才养出来,希望你从一开始就带着它们走,希望帮到你。
本文还有配套的精品资源,点击获取