基因表达风险评分(Gene Expression Risk Score)是一种基于转录组数据(如RNA-seq或微阵列)计算个体或样本疾病风险的量化指标。它广泛应用于癌症预测、预后评估和个性化医疗中,例如在乳腺癌中使用Oncotype DX评分或在心血管疾病中评估基因表达模式。这种评分通过整合多个基因的表达水平,捕捉疾病相关的分子特征,从而提供比单一基因更鲁棒的风险估计。
本文将详细解析计算基因表达风险评分的完整流程,从数据预处理到最终加权求和,包括核心算法原理和生物信息学关键步骤。我们将使用Python代码示例(基于常见库如pandas、numpy和scikit-learn)来说明每个步骤,确保可操作性。假设我们有一个简化的示例数据集:10个样本(5个健康、5个患病),每个样本有5个基因的表达值。这些基因已通过文献或筛选确定为风险相关(例如,基因A、B、C、D、E)。
1. 数据获取与初步理解
基因表达数据通常来源于高通量测序(如RNA-seq)或芯片技术,存储为表达矩阵:行是基因,列是样本,值是表达水平(如FPKM、TPM或归一化计数)。风险评分计算的前提是数据已初步质量控制(QC),如去除低表达基因或异常样本。
关键步骤:
- 数据来源:公共数据库如TCGA(The Cancer Genome Atlas)或GEO(Gene Expression Omnibus)。例如,从TCGA下载乳腺癌RNA-seq数据。
- 数据结构:一个典型的表达矩阵如下(假设值已初步对数转换):
| Gene | Sample1 | Sample2 | … | Sample10 |
|---|---|---|---|---|
| GeneA | 5.2 | 4.8 | … | 6.1 |
| GeneB | 3.1 | 3.5 | … | 4.2 |
| … | … | … | … | … |
- 为什么重要:原始数据往往有批次效应(batch effect)和技术变异,需要预处理以确保生物学信号主导。
Python示例:加载和探索数据
假设我们有一个CSV文件expression_data.csv,包含基因表达矩阵和样本标签(0=健康,1=患病)。
import pandas as pd
import numpy as np
# 加载数据
data = pd.read_csv('expression_data.csv', index_col=0) # 第一列为基因名
labels = pd.read_csv('sample_labels.csv', index_col=0) # 样本标签
# 查看数据形状和前几行
print("数据形状:", data.shape) # 例如 (5, 10) 表示5个基因,10个样本
print(data.head())
# 输出示例:
# Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 Sample7 Sample8 Sample9 Sample10
# GeneA 5.2 4.8 5.5 4.9 5.1 6.0 5.8 6.2 5.9 6.1
# GeneB 3.1 3.5 3.2 3.4 3.3 4.0 3.9 4.1 3.8 4.2
# GeneC 2.8 2.9 2.7 3.0 2.6 3.5 3.4 3.6 3.3 3.7
# GeneD 4.5 4.2 4.6 4.3 4.4 5.0 4.9 5.1 4.8 5.2
# GeneE 1.9 2.0 1.8 2.1 1.7 2.5 2.4 2.6 2.3 2.7
在这个阶段,检查缺失值和分布:data.isnull().sum() 和 data.describe()。
2. 数据标准化:消除技术变异和可比性
标准化是风险评分计算的核心第一步,确保不同样本和基因间的表达值可比。原始表达数据受测序深度、文库大小和批次影响,直接使用会导致偏差。
核心原理:
- 为什么标准化:RNA-seq数据常有零膨胀和过度离散;微阵列数据有背景噪声。标准化将数据转换为相对表达或Z-score形式,突出生物学变异。
- 常见方法:
- CPM/TPM/RPKM:针对测序数据,调整文库大小(library size)。
- Quantile Normalization:使所有样本分布相同,常用于微阵列。
- Z-score标准化:按基因计算((x - mean) / std),使每个基因均值为0、标准差为1,便于加权。
- Log转换:对原始计数应用log2(x+1)以稳定方差。
关键步骤:
- 质量控制:移除低表达基因(例如,平均CPM < 1)。
- 批次校正:使用ComBat(来自pycombat库)如果数据来自多批次。
- 应用标准化:选择适合数据类型的方法。
Python示例:标准化流程
我们使用Z-score标准化,按基因(行)计算,便于后续加权。
from scipy import stats
import numpy as np
# 假设data是表达矩阵(基因 x 样本)
# Step 1: Log转换(如果原始是计数)
log_data = np.log2(data + 1) # 避免log(0)
# Step 2: Z-score标准化(按基因,即行)
normalized_data = stats.zscore(log_data, axis=1) # axis=1表示按行标准化
# 如果有批次效应,使用ComBat校正(需安装:pip install combat)
# from combat.pycombat import pycombat
# batch = [0,0,0,0,0,1,1,1,1,1] # 假设前5个样本批次1,后5个批次2
# corrected_data = pycombat(normalized_data, batch)
print("标准化后数据(前3行):")
print(normalized_data[:3])
# 输出示例(近似值):
# [[ 0.2 -0.8 0.5 -0.6 0.1 1.2 0.9 1.4 1.0 1.3 ]
# [-0.9 0.3 -0.7 0.1 -0.3 1.1 0.8 1.2 0.7 1.4 ]
# [-0.5 -0.2 -0.7 0.1 -0.8 1.0 0.7 1.1 0.6 1.2 ]]
解释:每个基因的表达值现在围绕0分布,正值表示高于平均表达。这步确保高表达基因不会主导评分。
3. 基因选择与特征工程:聚焦风险相关基因
并非所有基因都用于风险评分。通常,使用预定义的基因集(如从文献或机器学习筛选)。
核心原理:
- 为什么需要选择:全基因组数据维度高(>20,000基因),噪声大。选择风险相关基因(如与疾病通路相关的)可提高模型特异性。
- 常见方法:
- 单变量筛选:t-test或ANOVA比较健康 vs. 患病组的基因表达差异。
- 多变量方法:LASSO回归或随机森林选择特征。
- 预定义集:如MSigDB中的基因集,或已知签名(如70基因签名用于乳腺癌)。
关键步骤:
- 计算每个基因的差异表达(p-value < 0.05)。
- 选择top-N基因(例如,20-50个)。
- 确保基因方向性:风险基因通常上调(正值系数)。
Python示例:基因筛选
使用t-test筛选差异表达基因。
from scipy.stats import ttest_ind
from sklearn.feature_selection import SelectKBest, f_classif
# 假设labels是样本标签(0健康,1患病),形状(10,)
healthy = normalized_data[:, labels == 0] # 健康样本
diseased = normalized_data[:, labels == 1] # 患病样本
# 单变量t-test
p_values = []
for i in range(normalized_data.shape[0]): # 遍历每个基因
t_stat, p_val = ttest_ind(healthy[i, :], diseased[i, :])
p_values.append(p_val)
# 选择p-value最小的前3个基因作为风险基因
gene_names = data.index.tolist()
selected_indices = np.argsort(p_values)[:3] # top 3
selected_genes = [gene_names[i] for i in selected_indices]
print("选中的风险基因:", selected_genes) # 示例: ['GeneA', 'GeneD', 'GeneE']
# 提取选中基因的数据
risk_data = normalized_data[selected_indices, :]
解释:这步确保评分基于生物学相关的基因。例如,如果GeneA在患病组显著上调,它将贡献正风险。
4. 加权求和:计算风险评分
最终,风险评分通过加权求和计算:Score = Σ (w_i * x_i),其中w_i是基因i的权重,x_i是其标准化表达值。
核心原理:
- 公式:Risk Score = β_0 + Σ (β_i * Gene_i),其中β_i是系数(权重),常从Cox比例风险模型或线性回归拟合得到。
- 权重来源:
- 简单加权:使用差异倍数(fold-change)或相关系数。
- 高级算法:Cox回归(生存分析)或弹性网络(L1/L2正则化)训练模型,输出系数。
- 方向性:风险基因权重为正(上调增加风险),保护基因为负。
- 变体:有时加总后加log转换或阈值处理。
关键步骤:
- 训练模型:使用训练集拟合系数(例如,Cox模型预测生存时间)。
- 计算评分:对新样本应用公式。
- 风险分层:根据评分阈值(如中位数)分高/低风险组。
Python示例:加权求和计算
假设我们从Cox模型获得权重(实际中用lifelines库拟合)。这里简化:使用t-statistic作为权重(正值表示风险基因)。
from lifelines import CoxPHFitter # 需安装: pip install lifelines
# 假设有生存数据(时间time,事件event),用于训练权重
survival_data = pd.DataFrame({
'time': [10, 12, 8, 15, 9, 11, 13, 7, 14, 16], # 生存时间
'event': [1, 1, 0, 1, 0, 1, 1, 0, 1, 1], # 事件(1死亡,0删失)
'GeneA': risk_data[0, :], # 选中基因的表达
'GeneD': risk_data[1, :],
'GeneE': risk_data[2, :]
})
# 拟合Cox模型获取系数(权重)
cph = CoxPHFitter()
cph.fit(survival_data, duration_col='time', event_col='event')
coefficients = cph.params_.values # 权重: [beta_A, beta_D, beta_E]
print("Cox模型系数(权重):", coefficients)
# 计算风险评分(对所有样本)
risk_scores = np.dot(coefficients, risk_data) # 加权求和: Σ w_i * x_i
# 添加常数项(如果模型有)
intercept = cph.params_['GeneA'] * 0 # 简化,无截距
final_scores = intercept + risk_scores
print("风险评分(每个样本):", final_scores)
# 输出示例(近似):
# 权重: [0.5, -0.2, 0.3] # GeneA和E正权重(风险),GeneD负(保护)
# 评分: [1.2, -0.5, 0.8, -0.3, 1.0, 1.5, 1.3, -0.4, 1.4, 1.6]
解释:对于Sample1,Score = 0.50.2 + (-0.2)(-0.5) + 0.3*1.2 ≈ 1.2(高风险)。高分表示更高风险。实际中,使用交叉验证验证模型(如AUC > 0.7)。
5. 生物信息学中的关键步骤与验证
关键步骤总结:
- 预处理:QC和标准化(占计算时间的40%)。
- 特征选择:避免过拟合,使用独立验证集。
- 模型训练:Cox或机器学习,确保系数生物学合理(例如,通过通路富集分析验证)。
- 验证:内部(交叉验证)和外部(独立队列)验证。使用Kaplan-Meier曲线比较高低风险组生存差异。
- 可视化:热图显示基因表达,箱线图显示评分分布。
潜在挑战与优化:
- 噪声:使用鲁棒标准化。
- 多组学整合:结合突变或甲基化数据。
- 工具:R的
survival包或Python的scikit-survival。
通过这个流程,基因表达风险评分从原始数据转化为可解释的风险指标,帮助临床决策。实际应用需根据具体疾病调整参数,并咨询生物统计学家。
