Gene symbol、Ensembl gene ID 和 Entrez gene ID 都可以标识基因,但它们来自不同维护体系,不是可以随意互换的字符串格式。转换时真正要确定的是:物种、来源数据库、注释版本,以及遇到一对多和未匹配记录时怎样处理。
常见资源与 R 接口:
| 资源或接口 | 适合任务 | 数据位置 |
|---|---|---|
Ensembl / biomaRt |
Ensembl IDs、坐标和大量 attributes 的在线查询 | 在线数据库 |
org.Hs.eg.db / org.Mm.eg.db |
常见 gene IDs 与 annotations 的本地映射 | 已安装的 OrgDb package |
AnnotationDbi::select() |
统一查询 OrgDb 等 annotation packages | 本地 package |
clusterProfiler::bitr() |
富集分析前的常见 ID 转换 | 依赖 OrgDb |
AnnotationHub |
按物种和版本发现大型 annotation resources | 本地缓存 + 在线索引 |
不存在对所有物种、版本和目标字段都最好的单一方法。选择接口之前,先确定结果需要哪一种 ID 作为主键。
先识别输入 ID
典型形式包括:
TP53 gene symbol
ENSG00000141510 Ensembl gene ID
ENSG00000141510.18 带版本号的 Ensembl gene ID
7157 Entrez gene ID
带点号的 Ensembl 版本后缀可能需要拆开后再查询:
ensembl_with_version <- c(
"ENSG00000141510.18",
"ENSG00000146648.22"
)
ensembl_id <- sub("\\..*$", "", ensembl_with_version)
不要直接修改原始列。保留原始 ID,并建立单独的标准化查询列,后续才能追踪哪些变化来自清理、哪些来自数据库映射。
Gene symbol 的大小写也与物种有关。人类 symbol 常以大写展示,小鼠 symbol 常采用首字母大写形式;把字符串机械转换为大写或小写不等于完成物种映射。
使用 biomaRt 查询 Ensembl
连接人类 Ensembl gene dataset:
library(biomaRt)
ensembl <- useMart(
biomart = "ensembl",
dataset = "hsapiens_gene_ensembl"
)
从 HGNC symbol 查询 Ensembl ID 与坐标:
symbols <- c("AATK", "STAT3", "TP53")
annotation <- getBM(
attributes = c(
"hgnc_symbol",
"ensembl_gene_id",
"chromosome_name",
"start_position",
"end_position",
"strand"
),
filters = "hgnc_symbol",
values = symbols,
mart = ensembl
)
annotation
attributes 决定返回字段,filters 决定输入 ID 类型。查询坐标时还必须记录 Ensembl release 和 genome assembly;同一个 gene ID 的边界可能随 annotation 更新。
在线查询适合字段丰富、物种选择灵活的任务,但结果依赖网络和数据库状态。正式项目应保存查询代码、返回表和版本信息,不能只保存最终转换后的一列 ID。
使用 OrgDb 与 AnnotationDbi
人类常用 org.Hs.eg.db,小鼠常用 org.Mm.eg.db:
library(AnnotationDbi)
library(org.Hs.eg.db)
先查看支持的 key types 与 columns:
keytypes(org.Hs.eg.db)
columns(org.Hs.eg.db)
从 symbol 查询 Ensembl 与 Entrez ID:
annotation <- select(
org.Hs.eg.db,
keys = c("AATK", "STAT3", "TP53"),
keytype = "SYMBOL",
columns = c("SYMBOL", "ENSEMBL", "ENTREZID")
)
annotation
本地 annotation package 便于复现和批量查询,但其内容对应 package 构建时收录的数据库版本。记录:
packageVersion("org.Hs.eg.db")
select() 可能返回一对多关系,例如一个 symbol 对应多个历史或当前 identifiers。返回行数大于输入长度不是函数出错,而是映射关系本身需要决定。
使用 clusterProfiler::bitr()
富集分析流程中可以使用 bitr():
library(clusterProfiler)
converted <- bitr(
c("AATK", "STAT3", "TP53"),
fromType = "SYMBOL",
toType = c("ENSEMBL", "ENTREZID"),
OrgDb = org.Hs.eg.db
)
converted
bitr() 仍然依赖 OrgDb 的映射。它简化了接口,但不会自动解决重复、旧 symbol、物种错误或未匹配记录。用于 enrichment 前,应报告多少输入基因成功进入目标 ID 空间。
在数据框中保留映射轨迹
不要只取转换结果向量后按行位置塞回原表。先保留原始 key,再做显式连接:
input <- data.frame(
original_order = 1:4,
symbol = c("TP53", "STAT3", "AATK", "NOT_A_GENE")
)
mapping <- AnnotationDbi::select(
org.Hs.eg.db,
keys = unique(input$symbol),
keytype = "SYMBOL",
columns = c("ENSEMBL", "ENTREZID")
)
result <- merge(
input,
mapping,
by.x = "symbol",
by.y = "SYMBOL",
all.x = TRUE,
sort = FALSE
)
result <- result[order(result$original_order), ]
all.x = TRUE 保留未匹配输入。若映射是一对多,连接后同一原始行会展开成多行;这是需要审查的结果,不能用 !duplicated() 随意留下第一条。
使用个人封装
高频流程可以把标准化、查询与检查封装成函数。例如 evanverse::convert_gene_id() 接受向量或数据框,并在 symbol、Ensembl 与 Entrez ID 之间转换:
library(evanverse)
converted <- convert_gene_id(
query = c("AATK", "STAT3", "TP53"),
from = "symbol",
to = c("ensembl_id", "entrez_id"),
species = "human"
)
数据框输入:
converted <- convert_gene_id(
query = data.frame(gene = c("AATK", "STAT3")),
query_col = "gene",
from = "symbol",
to = "ensembl_id",
species = "human"
)
封装适合统一重复工作,但应能够暴露或记录底层 reference table、版本、匹配率和一对多处理规则。否则接口越方便,来源差异越容易被隐藏。
转换后的质量检查
至少记录以下数量:
n_input <- length(unique(input$symbol))
n_matched <- length(unique(result$symbol[!is.na(result$ENSEMBL)]))
n_unmatched <- n_input - n_matched
c(
input = n_input,
matched = n_matched,
unmatched = n_unmatched
)
并检查:
- 输入和 reference 是否属于同一物种;
- Ensembl IDs 是否带版本后缀;
- gene symbol 是否包含旧名、别名或不可识别值;
- 是否出现一对多或多对一;
- 转换后是否因重复映射改变行数;
- 未匹配记录是否被保留并单独查看;
- 坐标使用哪个 genome build;
- 数据库或 annotation package 版本是否记录。
Gene ID conversion 不是简单的字符串替换,而是一次数据库连接。最安全的结果不是只有“转换后的 ID”,而是同时保留原始 ID、目标 ID、映射来源、版本和匹配状态。