惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
罗磊的独立博客
SecWiki News
SecWiki News
The Register - Security
The Register - Security
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
IT之家
IT之家
博客园 - 聂微东
T
The Exploit Database - CXSecurity.com
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Vercel News
Vercel News
G
GRAHAM CLULEY
D
DataBreaches.Net
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
博客园_首页
雷峰网
雷峰网
T
Tenable Blog
Spread Privacy
Spread Privacy
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
Cisco Talos Blog
Cisco Talos Blog
V
Visual Studio Blog
J
Java Code Geeks
博客园 - Franky
The Cloudflare Blog
Apple Machine Learning Research
Apple Machine Learning Research
C
CERT Recently Published Vulnerability Notes
T
Threatpost
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
V
Vulnerabilities – Threatpost
Recent Announcements
Recent Announcements
Blog — PlanetScale
Blog — PlanetScale
Security Latest
Security Latest
U
Unit 42
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
K
Kaspersky official blog
有赞技术团队
有赞技术团队
B
Blog
腾讯CDC

Wslll

手搓一个ios记账应用:快捷指令、PWA应用、AI分析 一个AnthropicToOpenai的本地运行的API转换脚本(用于ClaudeCode等) 一种针对长篇幅学术文章的特征提取循环翻译模式 开源分享:经过运行验证的自动SNP Calling脚本 使用glnexus进行joint call的一些经验 wslll blog:基于Python的自托管博客应用 wslll blog的介绍以及2025年不稳定运行的原因 期刊发布:基于重测序的原始群体和改良群体的遗传多样性研究 使用cloudflare worker转发openai api并设置关键词屏蔽 期刊发布:遗传改良对世界水产养殖业发展的推动作用 你好,世界!
使用SimpleM计算有效检验数量
wslll · 2024-12-17 · via Wslll

什么是 SimpleM?

GWAS(全基因组关联研究)中,我们通常需要对数百万个单核苷酸多态性(SNPs)进行假设检验,从而发现与目标表型相关的遗传变异。然而,这种大规模的多重检验问题容易导致假阳性,因此需要对显著性水平进行矫正(如 Bonferroni 矫正)。

然而,基因组数据中的 SNPs 并非完全独立,它们通常呈现高度的连锁不平衡(Linkage Disequilibrium, LD)。因此,传统的多重检验方法可能会过于严格,导致我们错失真正的信号。

SimpleM 是一种用于计算 “有效检验数量”(Effective Number of Tests, Meff) 的统计方法。通过对遗传数据中 LD 矩阵的特征值分解(Eigenvalue Decomposition, EVD),SimpleM 能够估计 SNPs 的独立信息成分数量,从而提供一种合理的多重检验矫正标准。

有效检验数量(Meff)

有效检验数量的核心思想是通过度量数据的相关性,简化假设检验的规模:

  1. 直观解释
    Meff 是一个反映 SNP 独立性的信息量指标。对于高度相关的 SNPs(如位于同一个 LD 区域的变异),它们共享的大部分信息可以被归纳为一个“独立单元”。因此,实际需要检验的有效独立单元比总 SNP 数量要少。

  2. 数学定义
    在 SimpleM 方法中,基于 LD 矩阵的特征值 (\lambda_i) 分解。

  3. 应用场景
    Meff 被用来调整显著性阈值,比如替代传统 Bonferroni 矫正中的显著性水平。

这比直接使用 SNP 总数更合理,也能提高研究的统计效能。

代码示例

首先需要说明的是,本文提供的代码并非100%准确,仅仅为各位朋友提供参考信息。请各位在使用前仔细阅读斟酌。首先是SimpleM的R代码,也是计算的核心脚本。

#============================================================================
# simpleM_Ex.R 

#============================================================================
# License:  GPL version 2 or newer. 
# NO warranty. 

#============================================================================
# citation: 
#
# Gao X, Starmer J and Martin ER (2008) A Multiple Testing Correction Method for
# Genetic Association Studies Using Correlated Single Nucleotide Polymorphisms. 
# Genetic Epidemiology 32:361-369
#
# Gao X, Becker LC, Becker DM, Starmer J, Province MA (2009) Avoiding the high 
# Bonferroni penalty in genome-wide association studies. Genetic Epidemiology 
# (Epub ahead of print) 

#============================================================================
# readme: 
# example SNP file format:
# row => SNPs
# column => Unrelated individuals 

# The data file should contain only POLYMORPHIC SNPs. 

# Missing values should be imputed. 
# There should be NO missing values in the SNP data file.
# SNPs are coded as 0, 1 and 2 for the number of reference alleles. 
# SNPs are separated by one-character spaces. 

# You may need to change file path (search for "fn_In" variable) 
# depending on where your snp file is stored at.

#============================================================================
# Meff through the PCA approach 
# use a part of the eigen values according to how much percent they contribute
# to the total variation 
Meff_PCA <- function(eigenValues, percentCut){
    totalEigenValues <- sum(eigenValues)
    myCut <- percentCut*totalEigenValues
    num_Eigens <- length(eigenValues)
    myEigenSum <- 0
    index_Eigen <- 0

    for(i in 1:num_Eigens){
        if(myEigenSum <= myCut){
            myEigenSum <- myEigenSum + eigenValues[i]
            index_Eigen <- i
        }
        else{
            break
        }
    }   
    return(index_Eigen)
}

#============================================================================
# infer the cutoff => Meff
inferCutoff <- function(dt_My){
    CLD <- cor(dt_My)
    eigen_My <- eigen(CLD)

    # PCA approach
    eigenValues_dt <- abs(eigen_My$values)
    Meff_PCA_gao <- Meff_PCA(eigenValues_dt, PCA_cutoff)
    return(Meff_PCA_gao)
}

#============================================================================
PCA_cutoff <- 0.995

#============================================================================
# fix length, simpleM
fn_In <- "请修改这里的文件路径/snpSample.txt"
mySNP_nonmissing <- read.table(fn_In, colClasses="integer")     

numLoci <- length(mySNP_nonmissing[, 1])

simpleMeff <- NULL
fixLength <- 133 
i <- 1
myStart <- 1
myStop <- 1
while(myStop < numLoci){
    myDiff <- numLoci - myStop 
    if(myDiff <= fixLength) break

    myStop <- myStart + i*fixLength - 1
    snpInBlk <- t(mySNP_nonmissing[myStart:myStop, ])
    MeffBlk <- inferCutoff(snpInBlk)
    simpleMeff <- c(simpleMeff, MeffBlk)
    myStart <- myStop+1
}
snpInBlk <- t(mySNP_nonmissing[myStart:numLoci, ])
MeffBlk <- inferCutoff(snpInBlk)
simpleMeff <- c(simpleMeff, MeffBlk)

cat("Total number of SNPs is: ", numLoci, "\n")
cat("Inferred Meff is: ", sum(simpleMeff), "\n")

#============================================================================
# end 

下面是处理Raw数据生成矩阵并通过调用上面的simpleM_Ex.R 脚本进行计算的R代码

install.packages("data.table")
install.packages("corpcor")
# 加载必要的包
library(data.table)
library(corpcor)

# 读取基因型数据,使用plink获得的raw数据
genotype_data <- fread("修改为你的路径/my_genotype.raw", header=TRUE)

# 删除前6列非基因型信息(FID, IID, PAT, MAT, SEX, PHENOTYPE)
genotype_data <- genotype_data[, -(1:6), with=FALSE]

# 转置矩阵,使行表示SNP,列表示个体
genotype_matrix <- t(as.matrix(genotype_data))

# 检查基因型矩阵中是否有缺失值或无穷值
any(is.na(genotype_matrix))  # 返回TRUE则表示有NA值
any(is.infinite(genotype_matrix))  # 返回TRUE则表示有无穷值

# 使用平均数填充NA
#genotype_matrix[is.na(genotype_matrix)] <- rowMeans(genotype_matrix, na.rm = TRUE)

# 定义计算众数的函数
getmode <- function(v) {
  uniqv <- unique(v[!is.na(v)])  # 去除NA后获取唯一值
  uniqv[which.max(tabulate(match(v, uniqv)))]  # 返回出现次数最多的值
}

# 使用众数替换每行中的缺失值
for (i in 1:nrow(genotype_matrix)) {
  mode_value <- getmode(genotype_matrix[i, ])
  genotype_matrix[i, is.na(genotype_matrix[i, ])] <- mode_value
}

# 检查是否还有缺失值
any(is.na(genotype_matrix))  # 如果返回FALSE,说明所有缺失值已被填充

# 将转置后的矩阵保存为纯文本文件,供SimpleM使用
write.table(genotype_matrix, file="将矩阵写入的文本文件/snpSample.txt", row.names=FALSE, col.names=FALSE, quote=FALSE, sep=" ")


# 在R中运行脚本
source("修改为你的simpleM_Ex.R文件的保存路径/simpleM_Ex.R")

由于我使用的芯片分型,因此原始SNP数量就很少。如果你使用的重测序数据Call的SNP,情况可能很不一样。同样,仅供参考。