ウィルコクソン検定から得られる信頼区間
導入
数理統計の本には良く「信頼区間は検定方式の反転によって得られる」というようなことが書かれている.
と, 言うときにいま僕が手元で参照しているのは『現代数理統計学の基礎』(久保川達也, 共立出版)だが, これ以外にも表紙のどこかに「数理統計学」と入っているような本には同様のことが書かれていることが多いと思う.
両側検定,
帰無仮説:
対立仮説:
の検定統計量
とできるなら, これを
が得られる.
しかし具体例を複数やらないとちょっとわかりにくいかもしれない.
そこでここでは2標本のウィルコクソン検定(ウィルコクソンの順位和検定)を使って信頼区間を求めてみる.
とりあえず計算してみる
Rでは関数 wilcox.test
がウィルコクソン検定で, conf.int=TRUE
とすると信頼区間を出力する.
この信頼区間が帰無仮説を棄却しない
library(ggplot2)
set.seed(123)
x <- rweibull(50,1.5)
y <- rweibull(50,1.5)
U <- outer(x,y,"-") #全部の組み合わせで差を計算
sx <- sort(U[lower.tri(U, diag = TRUE)])
pv_w <- sapply(sx,function(m)wilcox.test(x, y, mu=m)$p.value)
df4p <- data.frame(sx=sx,pv=pv_w)
m <- median(U)
null_wilcox <- wilcox.test(x,y, conf.int = TRUE, conf.level = 0.95)
ggplot(df4p, aes(x=sx))+
geom_step(aes(y=pv))+
geom_rug(aes(x=sx), alpha=0.1)+
annotate(geom="point", x=null_wilcox$estimate,y=1,
colour="royalblue")+
annotate(geom = "errorbarh",
xmin=null_wilcox$conf.int[1],
xmax=null_wilcox$conf.int[2],
y=1-0.95,
height=0.075,
colour="royalblue")+
theme_bw(18)+
labs(y="p-value", x="U")
図の青いエラーバーが95%信頼区間, 曲線がp値.
ちなみに信頼区間の幅を0%まで縮めたもの(図中の丸いマーカー)はホッジス・レーマン(Hodges–Lehmann)推定量と呼ばれる.
結局, これが母集団のなにに対応する量を推定しようとしているのかを知るために, 改めてウィルコクソン検定を紹介する.
ウィルコクソン検定の紹介
2群,
どちらも同じ分布に従っているとすると
Rによる計算例:
#Rのコード
set.seed(123)
x <- rnorm(2)
y <- rnorm(2)
R <- rank(c(x,y)) #まとめて順位をつける
#最初の2列がyグループ
> round(rbind(c(x,y),R),2)
[,1] [,2] [,3] [,4]
1.56 0.07 -0.56 -0.23
R 4.00 3.00 1.00 2.00
Yグループの順位の取りうる値はすべて書き出せる.
(1,2), (1,3), (1,4)
(2,3), (2,4)
(3,4)
これより, Yグループの順位の合計もすべて書き出せる.
3, 4, 5
5, 6
7
この頻度を表にすると,
順位の合計 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|
度数 | 1 | 1 | 2 | 1 | 1 |
確率 | 1/6 | 1/6 | 2/6 | 1/6 | 1/6 |
となる.
Rでシミュレーションしてみるとこの数え上げと同じ比の度数になることがわかる:
set.seed(1234)
W <- integer(10000)
for(i in 1:10000){
x <- rnorm(2)
y <- rnorm(2)
R <- rank(c(y,x))
W[i] <- sum(R[1:2]) #最初のn個がYの順位
}
barplot(table(W))
ちなみに, 次のように漸化式を作るともう少し現実的な時間で計算できる:
ここでは
と変換して取りうる値の最小値が0になるようにしている.
R の wilcox.test
が返す値もこの方式である.
この順位の合計を検定統計量にした検定を考えていく.
さて, Xグループの順位の分布は, 分布どうしで平均や中央値が同じとしても, 分布どうしの形状が違うときは一様にならない.
同じ分布でシミュレーション:
rlis1 <- vector("list", 10000)
for(i in 1:10000){
x <- rnorm(2)
y <- rnorm(2)
R <- rank(c(y,x))
rlis1[[i]] <- R[1:2] #最初のn個がYの順位
}
barplot(table(unlist(rlis1)))
平均や中央値が同じで分散が違う分布でシミュレーション:
rlis2 <- vector("list", 10000)
for(i in 1:10000){
x <- rnorm(2,0,1) #分散1
y <- rnorm(2,0,2) #分散2^2
R <- rank(c(y,x))
rlis2[[i]] <- R[1:2] #最初のn個がYの順位
}
barplot(table(unlist(rlis2)))
ここで改めて標準的な両側検定の記法で書くと,
帰無仮説:
対立仮説:
を検定するのがウィルコクソン検定である.
ここまでの議論では暗に
ところで, 検定統計量を
としたが, この
としたときの
(図は青線がマイナスでオレンジのチェックがプラス.
これが知りたいことであった.
〇〇検定と名前のついているものはいっぱいありややこしいが, 個人的には「母集団のなにに対応する量を推定しているのか」という視点から理解しようとするといいと思う.
より強い言い方をすると, そこをスキップすると実質的に帰無仮説ロンダリングになってしまうのではないかと思う.
シミュレーション
差の中央値と中央値の差は一般には一致しないので「2群で中央値が異なる」ことの検定には使えない場合がある.
中央値が(ついでに分散も)同じ分布でシミュレーションしてみよう.
library(ggplot2)
#中央値
mu <- qexp(0.5)
print(qnorm(0.5,mu,1))
#差の中央値(数値積分による力技で確認)
conv <- function(x){
#たたみ込み
integrate(function(y){dnorm(x+y,mu)*dexp(y)},-Inf,0)$value +
integrate(function(y){dnorm(x+y,mu)*dexp(y)},0,Inf)$value
}
conv <- Vectorize(conv)
m_root <- uniroot(function(x)integrate(conv,-Inf,x)$value-0.5, c(-1,0))
print(m_root$root)
#-0.1825963
#分散(数値積分による力技で確認)
v_e <- integrate(function(x)x^2*dexp(x), 0,Inf)$value -
integrate(function(x)x*dexp(x), 0,Inf)$value^2
v_n <- integrate(function(x)x^2*dnorm(x,mu,1), -Inf,Inf)$value -
integrate(function(x)x*dnorm(x,mu,1), -Inf,Inf)$value^2
print(v_e)
#1
print(v_n)
#1
#繰り返し計算
n1 <-100
n2 <-100
pv_simfun <- function(n1,n2, mu, m){
x1 <- rnorm(n1,mu,1)
x2 <- rexp(n2)
res_w <- wilcox.test(x1, x2, conf.int=TRUE)
cp <- res_w$conf.int[1] < m & m < res_w$conf.int[2]
data.frame(estimate=res_w$estimate,
pv = res_w$p.value,
cover = cp)
}
#手元のパソコンだと10秒くらいかかる
system.time({
res <- lapply(1:10000,
function(i){set.seed(i);pv_simfun(25, 25, mu, m_root$root)})
res <- do.call("rbind",res)
})
# user system elapsed
#10.068 0.051 10.212
#p値の経験分布
ggplot(res,aes(x=pv))+
stat_ecdf()+
geom_abline(slope = 1,intercept = 0, lty=2)+
theme_bw()+labs(x="nominal", y="actual")
ggsave("wilcox_p.png")
print(round(mean(res$cover),2))
#0.95
x軸の有意水準で棄却される確率がy軸なので, 中央値が同じ分布でも棄却されすぎていることがわかる.
一方で差の中央値の被覆確率については名目上の水準通りに保たれている.
> print(round(mean(res$cover),2))
[1] 0.95
このような場面でウィルコクソン検定を使って「中央値に差がある」という結論を出すのが, 上で「帰無仮説ロンダリング」と言ったものの例である.
Discussion