返回MR专题首页

LDSC 遗传相关性分析教程

ldsc.py --rg 到结果解读:MR 前的共享遗传基础评估

🧬 新手导读:LDSC和MR是什么关系?

LDSC不是MR替代品,而是前置评估工具:先看两性状是否存在共享遗传结构,再决定MR优先级。

背景介绍

LDSC可估计遗传相关性(rg)和截距,帮助判断性状间是否可能存在共同遗传基础,以及结果是否受群体结构偏差影响。

备注(统一三段)

适用人群:想在MR前做共享遗传结构评估、提升研究设计严谨性的同学。
常见错误:把rg显著当作因果证据是常见误区,LDSC仅支持相关性层面判断。
论文写法:论文可在“辅助分析”写LDSC目的、截距结果及其对MR策略的影响。

什么时候用LDSC?

ldsc.py 核心用法(单对性状)

munge_sumstats.py 统一格式,再用 ldsc.py --rg 计算遗传相关性。

# 0) 建议环境
conda create -n ldsc python=3.10 -y
conda activate ldsc
git clone https://github.com/bulik/ldsc.git
cd ldsc
pip install -r requirements.txt

# 1) 暴露GWAS标准化(munge)
python ./ldsc/munge_sumstats.py \
 --sumstats ./input/exposure_gwas.txt.gz \
 --N 350000 \
 --snp rsid \
 --a1 effect_allele \
 --a2 other_allele \
 --p p_value \
 --signed-sumstats beta,0 \
 --merge-alleles ./ref/w_hm3.snplist \
 --out ./ldsc_tmp/exposure

# 2) 结局GWAS标准化(munge)
python ./ldsc/munge_sumstats.py \
 --sumstats ./input/outcome_gwas.txt.gz \
 --N 420000 \
 --snp rsid \
 --a1 effect_allele \
 --a2 other_allele \
 --p p_value \
 --signed-sumstats beta,0 \
 --merge-alleles ./ref/w_hm3.snplist \
 --out ./ldsc_tmp/outcome

# 3) 计算遗传相关性 rg
python ./ldsc/ldsc.py \
 --rg ./ldsc_tmp/exposure.sumstats.gz,./ldsc_tmp/outcome.sumstats.gz \
 --ref-ld-chr ./ref/eur_w_ld_chr/ \
 --w-ld-chr ./ref/eur_w_ld_chr/ \
 --out ./ldsc_out/exposure_outcome_rg

# 4) 可选:分别估计h2,检查性状本身可解释遗传度
python ./ldsc/ldsc.py \
 --h2 ./ldsc_tmp/exposure.sumstats.gz \
 --ref-ld-chr ./ref/eur_w_ld_chr/ \
 --w-ld-chr ./ref/eur_w_ld_chr/ \
 --out ./ldsc_out/exposure_h2

批量rg模板(多个代谢物 vs 同一结局)

#!/usr/bin/env bash
set -euo pipefail

mkdir -p ./ldsc_out/batch_rg

OUTCOME="./ldsc_tmp/outcome.sumstats.gz"
REF="./ref/eur_w_ld_chr/"
MET_DIR="./ldsc_tmp/metabolites"  # 已munge完成的代谢物sumstats目录

for FILE in "${MET_DIR}"/*.sumstats.gz; do
 TRAIT=$(basename "${FILE}" .sumstats.gz)
 echo "[RUN] ${TRAIT} vs outcome"

 python ./ldsc/ldsc.py \
  --rg "${FILE},${OUTCOME}" \
  --ref-ld-chr "${REF}" \
  --w-ld-chr "${REF}" \
  --out "./ldsc_out/batch_rg/${TRAIT}_vs_outcome"
done

echo "Batch LDSC rg finished."

结果解读(重点看这几列)

R脚本:批量读取日志并自动注释

library(data.table)
library(stringr)
library(dplyr)

log_files <- list.files("./ldsc_out/batch_rg", pattern = "\\.log$", full.names = TRUE)

parse_one_log <- function(log_file) {
 lines <- readLines(log_file, warn = FALSE)
 rg_line_id <- grep("^\\./ldsc_tmp/.+\\.sumstats\\.gz\\s+\\./ldsc_tmp/.+\\.sumstats\\.gz", lines)[1]
 if (is.na(rg_line_id)) return(NULL)

 vals <- str_split(str_squish(lines[rg_line_id]), "\\s+")[[1]]
 if (length(vals) < 6) return(NULL)

 data.frame(
  p1 = vals[1],
  p2 = vals[2],
  rg = as.numeric(vals[3]),
  se = as.numeric(vals[4]),
  z = as.numeric(vals[5]),
  p = as.numeric(vals[6]),
  logfile = basename(log_file),
  stringsAsFactors = FALSE
 )
}

rg_table <- bind_rows(lapply(log_files, parse_one_log))
rg_table <- rg_table %>%
 mutate(
  p_fdr = p.adjust(p, method = "fdr"),
  direction = case_when(
   rg > 0 ~ "正相关",
   rg < 0 ~ "负相关",
   TRUE ~ "接近0"
  ),
  strength = case_when(
   abs(rg) >= 0.30 ~ "较强",
   abs(rg) >= 0.10 ~ "中等",
   TRUE ~ "较弱"
  ),
  interpretation = paste0(direction, " / ", strength)
 ) %>%
 arrange(p_fdr)

fwrite(rg_table, "./ldsc_out/batch_rg_summary.tsv", sep = "\t")