Yuanclaw / docs /GSEA_ID_MISMATCH_FIX.md
huashu's picture
Export YuanSeq to Hugging Face without binary assets
7e6a9d1
# GSEA模块ID类型不匹配问题修复
**日期**: 2025-12-26
**问题**: 用户选择ENTREZID格式的GMT文件但选择SYMBOL作为ID类型时,应用崩溃
---
## 问题描述
当用户:
1. 上传ENTREZID格式的GMT文件(基因ID是数字如12985)
2. 但在UI中选择了"Gene Symbol"作为ID类型
3. 运行GSEA时,尝试将GMT中的ENTREZID转换为SYMBOL
错误信息:
```
Error in $<-.data.frame: 替换数据里有657808行,但数据有882938
```
---
## 修复方案
### 1. 添加tryCatch错误捕获
**位置**: `modules/gsea_analysis.R:82-136`
```r
tryCatch({
# 创建ENTREZID到SYMBOL的映射
entrez_to_symbol <- setNames(res_clean$SYMBOL, res_clean$ENTREZID)
# 转换GMT文件
gmt$gene_symbol <- entrez_to_symbol[as.character(gmt$gene)]
# 统计和检查
...
}, error = function(e) {
# 捕获错误并提供用户友好的提示
showNotification("GMT ID类型不匹配!请选择正确的ID类型", type = "error")
return(NULL)
})
```
### 2. 映射率检查和警告
```r
# 统计转换结果
n_total <- nrow(gmt)
n_mapped <- sum(!is.na(gmt$gene_symbol))
n_unmapped <- sum(is.na(gmt$gene_symbol))
cat(sprintf("📊 转换结果: %d/%d 成功映射 (%.1f%%), %d 无法映射\n",
n_mapped, n_total, n_mapped/n_total*100, n_unmapped))
if (n_mapped < n_total * 0.5) {
# 如果超过50%无法映射,警告用户
showNotification("⚠️ GMT文件中超过50%的基因无法映射!\n\n建议:选择'Entrez ID'",
type = "warning", duration = 10)
# 不中断,继续使用部分数据
}
```
### 3. 详细的控制台输出
```
🔄 检测到GMT使用ENTREZID,正在转换为SYMBOL...
📊 GMT文件: 882938 行
📊 映射关系: 14610 个ENTREZID -> 14610 个SYMBOL
📊 转换结果: 657808/882938 成功映射 (74.5%), 225130 无法映射
✅ GMT转换完成: 186 个基因集, 657808 个基因
```
### 4. 用户友好的错误提示
**当映射率过低时(<50%)**:
```
⚠️ GMT文件中超过50%的基因无法映射!
您的GMT文件使用ENTREZID格式,但您选择了SYMBOL。
建议:
1. 在'GMT中的ID类型'中选择'Entrez ID'
2. 或者使用SYMBOL格式的GMT文件
当前映射:25.0% (100/400)
```
**当转换完全失败时**:
```
❌ GMT ID类型不匹配!
错误:替换数据里有657808行,但数据有882938
您的GMT文件使用ENTREZID格式,但您选择了SYMBOL。
请选择'Entrez ID'作为ID类型。
```
---
## 使用建议
### 推荐配置
**情况1: GMT文件使用ENTREZID(数字ID)**
```
GMT中的ID类型: Entrez ID ✅
```
**情况2: GMT文件使用SYMBOL(基因名)**
```
GMT中的ID类型: Gene Symbol ✅
```
### 不推荐的配置
```
❌ GMT文件: ENTREZID格式
ID类型选择: Gene Symbol
结果: 映射率可能很低,性能差
```
### 如何判断GMT文件格式
1. **打开GMT文件查看前几行**:
```
GO_0008150\t12985/71897/330122
GO_0019220\t54448/20299/14825
```
如果是纯数字 → ENTREZID格式
```
GO_0008150\tCsf3/Lypd6b/Cxcl3
GO_0019220\tIl1r2/Tnf/Il6
```
如果是基因名 → SYMBOL格式
2. **查看文件名**:
- `msigdb_v7.5.1_entrez.gmt` → ENTREZID
- `msigdb_v7.5.1_symbols.gmt` → SYMBOL
---
## 修复后的行为
### 场景1: ID类型匹配
```
GMT: ENTREZID
用户选择: Entrez ID
结果: ✅ 直接运行,无需转换
```
### 场景2: ID类型不匹配,但映射率可接受
```
GMT: ENTREZID (882,938 行)
用户选择: SYMBOL
映射: 657,808/882,938 (74.5%)
结果: ⚠️ 警告,但继续运行
```
### 场景3: ID类型不匹配,映射率过低
```
GMT: ENTREZID (1,000,000 行)
用户选择: SYMBOL
映射: 100,000/1,000,000 (10%)
结果: ⚠️ 警告,提示用户调整选择
但仍继续运行(使用部分数据)
```
### 场景4: 转换失败
```
GMT: ENTREZID
用户选择: SYMBOL
错误: 数据框维度不匹配
结果: ❌ 错误提示 + 友好建议
停止运行,等待用户调整
```
---
## 技术细节
### 错误捕获流程
1. **检测ID类型**: `grepl("^[0-9]+$", sample_genes)`
2. **创建映射**: `setNames(res_clean$SYMBOL, res_clean$ENTREZID)`
3. **转换GMT**: `entrez_to_symbol[as.character(gmt$gene)]`
4. **统计映射率**: 计算成功映射的百分比
5. **决策**:
- < 50%: 警告但继续
- 0: 错误并停止
- 其他: 正常运行
### 容错机制
1. **tryCatch**: 捕获所有错误
2. **警告而非错误**: 映射率>50%时继续运行
3. **友好的UI提示**: 清楚说明问题和解决方案
4. **详细日志**: 控制台输出完整信息
---
## 测试步骤
1. **测试正常情况**:
- GMT: ENTREZID
- 选择: Entrez ID
- 预期: ✅ 正常运行
2. **测试ID不匹配但可接受**:
- GMT: ENTREZID
- 选择: SYMBOL
- 预期: ⚠️ 警告但继续运行
3. **测试完全错误**:
- 使用错误格式的GMT
- 预期: ❌ 错误提示 + 停止运行
---
## 总结
### 修复的问题
1. ✅ 应用不再崩溃
2. ✅ 提供清晰的错误信息
3. ✅ 建议正确的配置
4. ✅ 在某些情况下容错继续运行
5. ✅ 详细的调试输出
### 用户体验改进
- ❌ 之前: 应用崩溃,用户不知道原因
- ✅ 现在: 友好的错误提示 + 解决方案
### 控制台输出
```
🔄 检测到GMT使用ENTREZID,正在转换为SYMBOL...
📊 GMT文件: 882938 行
📊 映射关系: 14610 个ENTREZID -> 14610 个SYMBOL
📊 转换结果: 657808/882938 成功映射 (74.5%), 225130 无法映射
⚠️ 映射率过低,建议用户调整ID类型选择
✅ GMT转换完成: 186 个基因集, 657808 个基因
```
---
**版本**: 3.3 Final
**状态**: ✅ 完全修复
**兼容性**: 向后兼容,不影响正常使用