bedtools区间操作:intersect/merge/coverage/closest
ChIP-seq 的 peak 落在哪些基因的 promoter 上?两个 peak set 有多少重叠?每个外显子的覆盖深度是多少?这些问题都一个答案:bedtools。
bedtools 的官方文档有 20+ 个子命令,但日常 90% 的场景只需要 5 个。本文覆盖最常用的 5 个子命令:intersect、merge、coverage、closest、genomecov,附带输出解读和常见坑。
实测环境:Debian 13,bedtools v2.31.1,Conda bioconda 安装。
1. BED 格式——先搞懂你操作的对象
BED(Browser Extensible Data)是 bedtools 的默认输入格式,最简单:
chr1 100 500 geneA 0 +chr1 600 900 geneB 0 -BED 最少 3 列(chrom, start, end),常见到 6 列:
| 列 | 字段 | 注意 |
|---|---|---|
| 1 | chrom | 染色体名,跟参考基因组一致 |
| 2 | start | 0-based(第一个碱基的位置是0) |
| 3 | end | 0-based,不包含该位置 |
| 4 | name | 基因名/peak ID |
| 5 | score | 0-1000,可忽略 |
| 6 | strand | + 或 - |
最重要的一点——BED 是 0-based,跟人类直觉的 1-based 不同:
| 坐标系统 | 第1个碱基 | 区间 [1,10] 的含义 | 工具 |
|---|---|---|---|
| 0-based | 位置0 | 第1到第10个碱基 | bedtools, BAM, bigWig |
| 1-based | 位置1 | 第1到第10个碱基 | SAM, GFF, VCF |
踩坑: 如果你从 GFF(1-based)手动转 BED,需要把 start 减 1:bed_start = gff_start - 1。
2. intersect——求交集,最核心的功能
2.1 基础用法
# 基因A(genes.bed)和peak(peaks.bed)在哪些区域重叠?bedtools intersect -a genes.bed -b peaks.bed输出:genes.bed 中与 peaks.bed 有重叠的行。
2.2 控制重叠策略——最容易被忽略的参数
默认情况下,只要有 1bp 重叠就算 hit。但生信中常常需要”至少 50% 重叠”:
# 要求基因区域至少50%被peak覆盖bedtools intersect -a genes.bed -b peaks.bed -f 0.5
# 要求重叠>=100bpbedtools intersect -a genes.bed -b peaks.bed -F 0.5 -e-f 的含义是:重叠区域占 -a 区域的至少 1bp。具体公式:
用 -f 0.5 即要求 overlap_ratio ≥ 50%。
几个常用组合:
| 参数 | 含义 | 场景 |
|---|---|---|
-f 0.5 | overlap占A的≥50% | peak注释到基因 |
-F 0.5 | overlap占B的≥50% | 基因筛选被peak完全覆盖的 |
-u | A中至少有1个B重叠即输出 | 去重模式,A每行最多输出一次 |
-v | 反向:输出没重叠的 | 找”没被peak覆盖的基因” |
-wa -wb | 同时输出A和B的行 | 想知道”哪个peak落在哪个基因” |
2.3 实战:peak 注释到基因 promoter
# 先扩展promoter区域(TSS±2000bp作为promoter)bedtools slop -i genes.bed -g chrom.sizes -b 2000 > promoters.bed
# 求peak和promoter的交集bedtools intersect -a peaks.bed -b promoters.bed -wa -wb > peak_promoter.txt2.4 输出解读
实测运行 intersect -wa -wb 的输出:
chr1 150 450 peak1 100 chr1 100 500 geneA 0 +chr1 580 850 peak2 80 chr1 600 900 geneB 0 -每一行前几列是 peak 信息(-wa),后面是基因信息(-wb)。如果想知道 overlap 的精确区间,用 -wo 额外输出重叠长度:
bedtools intersect -a genes.bed -b peaks.bed -wa -wb -wo3. merge——合并重叠区域
ChIP-seq 的原始 peak 经常有多个相邻 peak 实际上来自同一个结合事件。merge 把它们合起来:
# 基础合并bedtools merge -i peaks.bed
# 合并时要求重叠≥100bp才算连接bedtools merge -i peaks.bed -d 100
# 合并并保留统计信息(如:合并了多少个原始peak)bedtools merge -i peaks.bed -c 4,5 -o count,sum-c 4,5 表示对第4列做 count(多少个原始peak)、第5列做 sum(总信号强度)。
4. coverage——计算覆盖度
这在 RNA-seq 中用于计算每个基因的 reads 覆盖情况:
bedtools coverage -a genes.bed -b reads.bed输出解读(每列含义):
chr1 100 500 geneA 0 + 1 300 400 0.7500000 │ │ │ │ reads数 ───────┘ │ │ │ covered bases ──────────┘ │ │ gene length ───────────────┘ │ coverage ratio ────────────────────────┘如果 coverage_ratio = 0.75,说明该基因 75% 的区域有 reads 覆盖。
生信场景: RNA-seq 的基因表达量化(老的 featureCounts 前身就是类似逻辑),或者 ChIP-seq 的 peak 富集度评估。
5. closest——找最近邻
“每个基因 TSS 最近的 ChIP-seq peak 是哪个?”
bedtools closest -a genes.bed -b peaks.bed -d-d 输出额外一列:两个区间之间的距离(bp)。如果重叠则为 0。
6. slop——扩展/收缩区间
# 每个基因上下游各扩展200bpbedtools slop -i genes.bed -g chrom.sizes -b 200
# 只向上游扩展(5'方向)bedtools slop -i genes.bed -g chrom.sizes -l 500 -r 0
# 对于正链基因,-l 代表上游(5'端);对于负链基因,自动翻转# 用 -s 参数根据 strand 自动判断方向:bedtools slop -i genes.bed -g chrom.sizes -l 2000 -r 500 -s注意: -g chrom.sizes(染色体大小文件)是必须的——否则 slop 不知道染色体边界在哪里,可能导致区间超出染色体范围。
chrom.sizes 文件制作:
samtools faidx ref.facut -f1,2 ref.fa.fai > chrom.sizes7. genomecov——生成覆盖轨迹
生成全基因组的覆盖度 bedGraph,之后可转为 bigWig 上传到 UCSC:
bedtools genomecov -i reads.bed -g chrom.sizes -bg > coverage.bedgraph
# -bg 输出 bedGraph 格式# -bga 连零覆盖区域也输出(文件更大但更完整)# -split 对包含N>CIGAR的BAM输入时,避免把intron区域也算进去转 bigWig:
bedGraphToBigWig coverage.bedgraph chrom.sizes coverage.bw8. 踩坑记录
坑1:BED 坐标 0-based vs 1-based 搞混
症状:注释时发现偏移了 1bp。
排查:检查你的输入是 BED(0-based)还是 GFF(1-based)。不确定就用 head 看区间长度是否等于 end-start。对 BED 来说这是对的,对 GFF 来说 end-start+1 才是实际长度。
坑2:染色体名不匹配
症状:intersect 输出为空,明明两个文件都有 chr1。
原因:BED A 写的是 chr1,BED B 写的是 1。bedtools 把它们当不同染色体。
# 查看双方用了什么染色体名cut -f1 genes.bed | sort -ucut -f1 peaks.bed | sort -u坑3:sort-buffer-size 不够导致运行极慢
bedtools 处理大型 BED 文件时,如果没排序且没指定 sort 参数会巨慢:
# 先排序再操作sort -k1,1 -k2,2n genes.bed > genes_sorted.bedbedtools intersect -a genes_sorted.bed -b peaks_sorted.bed -sorted-sorted 参数跳过 bedtools 内部的排序,处理 GB 级文件时速度提升 5-10 倍。
坑4:merge 后原始信息丢失
merge 默认只保留染色体和坐标,其他列全部丢弃。要用 -c 和 -o 把关键信息保留下来。
9. 小结
| 子命令 | 功能 | 核心参数 |
|---|---|---|
| intersect | 求交集 | -f(重叠比例), -v(反向), -wa -wb(输出双方) |
| merge | 合并重叠 | -d(最大间距) |
| coverage | 覆盖度 | -d(逐碱基覆盖) |
| closest | 最近邻 | -d(输出距离) |
| slop | 扩展区间 | -l(左), -r(右), -s(按链) |
| genomecov | 覆盖轨迹 | -bg(bedGraph输出) |
本文于 2025-03-18 在 Debian 13 上实测完成。bedtools v2.31.1,测试数据均为模拟 BED 文件。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!