SNPデータの読み込み、GWA解析にgastonを用いる。Rのパッケージインストーラで簡単にダウンロード・インストールできる。また、多変量正規分布にしたがう乱数を発生させるためにmvtnormを用いる。こちらも読み込んでおく。

require(gaston) # for reading a vcf file and performing GWAS
require(mvtnorm) # 多変量正規分布に従う乱数の発生

GWASの実行

データの読み込み

 まず、vcf 形式のマーカー遺伝子型データ(McCouch ら 2016) を読み込む。vcf 形式のデータの読み込みには、gastonパッケージに含まれる関数read.vcfを用いる。

# vcfファイルの読み込み
bm <- read.vcf("data/HDRA-G6-4-RDP1-RDP2-NIAS.AGCT_MAF005MIS001NR_imputed.vcf.gz") 
## ped stats and snps stats have been set. 
## 'p' has been set. 
## 'mu' and 'sigma' have been set.
bm # データのsummaryが表示される
## A bed.matrix with 1568 individuals and 38769 markers.
## snps stats are set
## ped stats are set

GWASのシミュレーション

まず、疑似乱数の種をセットしておく。これにより、以下の解析で同じ結果が得られる。

set.seed(20210622)

データの準備。計算負荷を小さくするためにデータ数を減らす。ここでは、客観的な方法(k-medoids法)を用いて予め選んでおいた代表的な500系統を解析に用いる。なお、k-medioids法での代表選びのためのRコードはhttps://rpubs.com/hiroiwata/627490にある。

id.med <- read.csv("data/id_med.csv", row.names = 1)$id.med  # 代表500系統のid
bm.sim <- bm[id.med, ] # idのある系統を抽出
bm.sim <- select.snps(bm.sim, maf > 0.05) # MAFが5%以下のものを除いておく
bm.sim
## A bed.matrix with 500 individuals and 36502 markers.
## snps stats are set
## ped stats are set

500系統の36,502マーカーのデータとなっている。

繰り返し利用することになる血縁行列とその固有値分解を予め行っておく。

standardize(bm.sim) <- "mu_sigma"
grm <- GRM(bm.sim)
eigen.grm <- eigen(grm)

全SNPから、QTN (quantitative trait nucleotides)を無作為に選ぶ。

n <- ncol(bm.sim) # 全SNP数
n.qtn <- 6 # QTNの数
qtn.id <- sample(n, n.qtn) # n.qtn個のSNPをQTNとして無作為に選ぶ
X.qtn <- as.matrix(bm.sim[, qtn.id]) # QTNの遺伝子型スコアを抜き出す

次に、シミュレーションにおけるQTNの効果を決め、それらQTNによる遺伝変異を全系統について計算する。

w.qtn <- rep(1.0, n.qtn) # 主働遺伝子の効果を、ここでは全て1.0とする
g.qtn <- as.vector(X.qtn %*% w.qtn) # QTNによる変異を全系統について計算
var(g.qtn) # QTN効果による遺伝分散
## [1] 6.607365

効果の小さな遺伝子(ポリジーン、微働遺伝子)による効果を擬似的に生成する。生成には、多変量正規分布からの乱数を用いる。QTNによる遺伝変異の大きさに応じて発生させるように、先にQTNによる遺伝変異の分散(遺伝分散)を計算し、その分散に応じてポリジーンによる効果の大きさを調節する。

# QTNの遺伝分散の何割かをポリジーンによる遺伝分散とする
g.var.ratio <- 0.5 # QTNによる遺伝分散の50%をポリジーンによる遺伝分散にする
# 多変量正規乱数としてポリジーン効果を生成
g.poly <- as.vector(rmvnorm(1, sigma = grm * var(g.qtn) * g.var.ratio)) 
var(g.poly) # ポリジーン効果による分散
## [1] 3.010467

QTNの効果と微働遺伝子の効果を足し合わせて全系統の遺伝変異(遺伝子型値)を計算する。

g <- g.qtn + g.poly # 遺伝子型値 = QTNの効果 + ポリジーン効果
var(g) # 遺伝分散
## [1] 12.18517

次に、指定した遺伝率に従って環境変異を発生させる。

he <- 0.5 # 遺伝率。ここでは、表現型分散の50%が遺伝分散とする。
var.e <- (1 - he) / he * var(g) # 環境分散を計算する
e <- rnorm(length(g), sd = sqrt(var.e)) # var.eを分散にもつ環境変異を生成
var(e) # 環境分散
## [1] 12.1407

最後に、遺伝変異(遺伝子型値)に環境変異を加え、表現型変異(表現型値)を計算する。

y <- g + e # 遺伝変異に環境変異を加えて表現型変異を計算する
var(y) # 表現型分散
## [1] 24.70915

擬似的に生成した表現型値\(y\)を用いてGWASを行ってみる。

# GWASの実行
gwa.sim <- association.test(bm.sim, Y = y, 
                            method = "lmm", response = "quantitative", 
                            test = "wald", eigenK = eigen.grm, p = 4)

マンハッタンプロットを描く。

fdr.thresh <- 0.05 # 偽発見率のしきい値
fdr <- p.adjust(gwa.sim$p, method = "BH")
col <- rep("black", nrow(gwa.sim))
col[gwa.sim$chr %% 2 == 1] <- "gray50"
col[fdr < fdr.thresh] <- "green"
res <- manhattan(gwa.sim, pch = 20, col = col)

QTNとして検出されたSNPを示す。

res[fdr < fdr.thresh,]
##       chr      pos                 id A1 A2 freqA2        h2      beta
## 4534    1 40886543    SNP-1.40885499.  G  A  0.094 0.3965221  1.760882
## 4535    1 40888164    SNP-1.40887120.  G  A  0.096 0.3966243  1.677028
## 4536    1 40919729    SNP-1.40918685.  G  C  0.100 0.3961781  1.837236
## 4544    1 40971632    SNP-1.40970588.  C  T  0.100 0.3991273  1.883018
## 15056   4 31085326    SNP-4.30900214.  C  T  0.416 0.3957396  1.175803
## 15063   4 31121686    SNP-4.30936574.  T  A  0.382 0.3986050  1.300756
## 15115   4 31399386    SNP-4.31214283.  G  A  0.417 0.3534822  1.152306
## 15117   4 31401844    SNP-4.31216741.  C  T  0.420 0.3478513  1.198118
## 15118   4 31404256    SNP-4.31219153.  A  G  0.417 0.3503540  1.209181
## 27222   9  4215265     SNP-9.4214264.  A  T  0.897 0.4535143 -2.405386
## 27223   9  4218943     SNP-9.4217942.  A  G  0.894 0.4531454 -2.472885
## 33948  11 27998654   SNP-11.27527039.  G  A  0.085 0.4269134  1.558582
## 33953  11 28004683 SNP-11.27533068ct.  C  T  0.097 0.4128545  1.611712
## 33954  11 28005367   SNP-11.27533752.  T  A  0.088 0.4204711  1.686909
## 33956  11 28006840   SNP-11.27535225.  C  T  0.093 0.4128481  1.683128
## 33957  11 28007825   SNP-11.27536210.  T  C  0.092 0.4165065  1.663831
## 33958  11 28008519   SNP-11.27536904.  A  C  0.090 0.4190640  1.690244
## 33959  11 28008663   SNP-11.27537048.  G  A  0.094 0.4321907  1.574322
## 33962  11 28010508   SNP-11.27538893.  C  T  0.091 0.4192054  1.689171
## 33964  11 28011447   SNP-11.27539832.  C  A  0.053 0.4287450  2.018508
## 33965  11 28011849   SNP-11.27540234.  G  A  0.094 0.4186767  1.698562
## 33967  11 28012393   SNP-11.27540778.  T  C  0.093 0.4137468  1.639406
## 35443  12 15864073   SNP-12.15861368.  A  G  0.130 0.4010476  2.024688
##              sd            p     coord
## 4534  0.3909873 6.678630e-06 0.1096810
## 4535  0.3878442 1.532436e-05 0.1096853
## 4536  0.3909915 2.615469e-06 0.1097700
## 4544  0.4162502 6.074939e-06 0.1099093
## 15056 0.2696611 1.298856e-05 0.3934265
## 15063 0.2559100 3.717847e-07 0.3935241
## 15115 0.2393093 1.471030e-06 0.3942690
## 15117 0.2380599 4.832643e-07 0.3942756
## 15118 0.2372026 3.438570e-07 0.3942821
## 27222 0.5747216 2.847809e-05 0.7359077
## 27223 0.5645902 1.186990e-05 0.7359176
## 33948 0.3587717 1.397745e-05 0.9234598
## 33953 0.3399142 2.121158e-06 0.9234759
## 33954 0.3515551 1.599215e-06 0.9234778
## 33956 0.3430037 9.246687e-07 0.9234817
## 33957 0.3460448 1.523432e-06 0.9234844
## 33958 0.3484469 1.229678e-06 0.9234862
## 33959 0.3515774 7.538696e-06 0.9234866
## 33962 0.3472309 1.146353e-06 0.9234916
## 33964 0.4666217 1.519856e-05 0.9234941
## 33965 0.3440694 7.946172e-07 0.9234952
## 33967 0.3431801 1.778414e-06 0.9234966
## 35443 0.3292835 7.808718e-10 0.9687134

次に、QTNとしたSNPの検定の結果、および、マンハッタンプロットのx軸上での位置を確認する。

res[qtn.id,]
##       chr      pos               id A1 A2 freqA2        h2       beta        sd
## 15115   4 31399386  SNP-4.31214283.  G  A  0.417 0.3534822  1.1523060 0.2393093
## 33967  11 28012393 SNP-11.27540778.  T  C  0.093 0.4137468  1.6394056 0.3431801
## 28516   9 18959418  SNP-9.18958417.  C  A  0.677 0.4407520 -0.2602716 0.4279641
## 35443  12 15864073 SNP-12.15861368.  A  G  0.130 0.4010476  2.0246880 0.3292835
## 4544    1 40971632  SNP-1.40970588.  C  T  0.100 0.3991273  1.8830178 0.4162502
## 15568   5   434397    SNP-5.434396.  G  A  0.407 0.4166602  0.9940285 0.2729061
##                  p     coord
## 15115 1.471030e-06 0.3942690
## 33967 1.778414e-06 0.9234966
## 28516 5.430799e-01 0.7754599
## 35443 7.808718e-10 0.9687134
## 4544  6.074939e-06 0.1099093
## 15568 2.701259e-04 0.4063281

QTNとしたSNPの位置をピンク色の垂線で表す。

res <- manhattan(gwa.sim, pch = 20, col = col)
abline(v = res$coord[qtn.id], col = "pink") # 垂線を引く

偽発見率、偽陽性率を計算する。なお、QTNの近くにあるSNPで検出されたものは真の陽性と判断することとする。

is.close2QTN <- rep(F, nrow(bm.sim@snps)) # QTNおよびその周辺であれば真になる
is.detected <-  rep(F, n.qtn) # そのQTNが検出されるかどうか
range <- 1e6 # QTNから1Mb以内は、正しく検出したものとする
for(i in 1:n.qtn) {
  qtn <- bm.sim@snps[qtn.id[i],] # 1つのQTNずつ調べる
  cond.chr <- bm.sim@snps$chr == qtn$chr # 染色体番号が一致するか?
  cond.pos1 <- bm.sim@snps$pos > qtn$pos - range # QTNの位置より-range〜
  cond.pos2 <- bm.sim@snps$pos < qtn$pos + range # +rangeに入っているか?
  is.close2QTN <- is.close2QTN | (cond.chr & cond.pos1 & cond.pos2) # QTNおよびその周辺
  is.detected[i] <- sum(fdr < fdr.thresh & (cond.chr & cond.pos1 & cond.pos2)) > 0
}

n.positive <- sum(fdr < fdr.thresh) # 陽性であったSNP数
n.positive
## [1] 23
n.negative <- sum(!(is.close2QTN)) # 陰性となるべき(QTLの近くにない)SNP数
n.negative
## [1] 35217
n.false.positive <- sum(!(is.close2QTN) & fdr < fdr.thresh) 
# 偽陽性のSNP数(本当は陰性なのに陽性になったSNP数)
n.false.positive
## [1] 2
fdr.obs <- n.false.positive / n.positive # 偽陽性のSNP数 / 陽性であったSNP数
fdr.obs # 偽発見率
## [1] 0.08695652
fpr.obs <- n.false.positive / n.negative # 偽陽性のSNP数 / 陰性となるべきSNP数
fpr.obs # 偽陽性率
## [1] 5.679075e-05
n.undetected <- sum(!(is.detected)) 
# 検出されなかったQTN数(近くにSNPが検出されなかったQTN)
n.undetected
## [1] 2
fnr.obs <- sum(!(is.detected)) / n.qtn # 検出されなかったQTN数 / 全QTN数
fnr.obs # 偽陰性率
## [1] 0.3333333