エンジニアのスキルを試すコードパズル ─この問題、あなたは解けますか?

第13回倉橋一成からの問題(第7回)解説編

そもそも「検定」とは

今回は、統計学の最も基礎的な手法の1つ、⁠検定」に焦点を当てた問題でした。

検定とは、ある仮説が統計的に正しいかまちがっているかを確かめる手法です。データには常にばらつき(誤差)があるため、統計学を使って議論するのです。

統計学では基本的に、取得したデータには「母集団」と呼ばれる、データの源となる集団があることを仮定しています(この仮定が統計学の難しいところでもあります⁠⁠。そして、その母集団からランダムサンプリングされて記録されたのが、手元にあるデータなのです。

そのことをわかっていただくため、今回はまずA~C群があって、そこからランダムサンプリングしてデータを作る、という過程をRで実践してもらいました。

最もよく使われるのは「t検定」と呼ばれるもので、2つのグループの平均値が等しいかどうかをチェックできます。今回の問題では、身長の平均値が等しいかどうかをチェックしてもらっています。

Rでランダムサンプリングをするには ~問1のポイント

ある集団の特性を知ろうとしたとき、その集団をすべて調査しなくても、ランダムサンプリングをすることで推測することができます。たとえば、A、B、C群の身長の平均値に違いがあるかどうかをチェックするためには、A~C群からランダムサンプリングを行い、t検定を行えば良いのです。

Rでは、sample()という関数が用意されているので、それを使ってランダムサンプリングを行います。

ポイントは、毎回同じ人をサンプリングするために、set.seed()を使って乱数の種を固定することです。正確には、replace=FALSEのオプションを入れることで、重複サンプルを防げます(デフォルトでFALSEになってます⁠⁠。

問1の解答は以下のとおりです。

(1)
heightA[sample(1:length(heightA), 100)]
(2)
heightB[sample(1:length(heightB), 100)]
(3)
heightC[sample(1:length(heightC), 100)]

この問題には、回答者16人みなさんが正解されていました。

サンプリングしたデータの平均値を検定するには ~問2のポイント

A群とB群からサンプリングしたデータの平均値を検定するときは、t検定を行います。Rでは、以下のようにt.test()関数を利用することで、A群のサンプルとB群のサンプルの平均値をt検定できます。

t.test(heightASmple, heightBSmple)

t検定では、比較する2群の分散が「等しい」と仮定するか、もしくは「等しくない」と仮定するかを選択します。2群の分散が等しいかどうかはわからないことが多いので、⁠等しくない」と仮定することが多いです。

この仮定をおいた検定を「ウェルチの検定」と呼ぶこともあります(正確には、2群の分散が等しいかどうかを検定してから、t検定をどうするか決めることもありますが、説明がややこしいのでまたの機会に……⁠⁠。

ちなみに、分散の仮定をどうするかは、t.test()関数のvar.equalオプションで選べます。デフォルトはFALSEなので、ウェルチの検定です。

t.test()関数を実行すると、P値が計算されます。P値は慣習的に、0.05未満だと「有意」と判定します。つまり、⁠2群の平均値が異なる」と判定されます。

今回のサンプリングデータでは、以下のように判定されました。

  • A vs B ⇒ 有意ではない
  • A vs C ⇒ 有意

この推測は、真の状態を正しく表しています。

データ作成とサンプリングを行う前に、set.seed()で乱数を固定した解答者は、同じ結果になっていました。

問2の解答は以下のとおりです。

t.test(heightASmple, heightBSmple)  # 有意じゃない
t.test(heightASmple, heightCSmple)  # 有意

検定の結果って正しいの? ~問3のポイント

ここで1つの疑問が出てきます。

サンプリングしたデータでは、本当に正しく推測できるのでしょうか?

今回は正しかったわけですが、本当にいつも正しいのでしょうか。

それを確かめるために、擬似的に1,000回サンプリングと検定を繰り返してもらいました。

1,000回サンプリングと検定を繰り返すことで、P値が1,000回分計算されます。そのP値の分布をみることで、⁠検定」というプロセスがどれほど信頼できるのかわかります。

問3の解答は以下のとおりです。

(1)
heightASmple  <- heightA[sample(1:length(heightA), 100)]
heightBSmple  <- heightB[sample(1:length(heightB), 100)]
PvalAB[i]  <- t.test(heightASmple, heightBSmple)$p.value
print(i)
(2)
heightASmple  <- heightA[sample(1:length(heightA), 100)]
heightCSmple  <- heightC[sample(1:length(heightC), 100)]
PvalAC[i]  <- t.test(heightASmple, heightCSmple)$p.value
print(i)

問4のポイント

P値が有意かどうかチェックしてみると、以下のことがわかります(みなさん、だいたいこれくらいの数でした⁠⁠。

  • A vs B ⇒ 1,000回中、約50回有意になる
  • A vs C ⇒ 1,000回中、約930回有意になる

A vs Bでは、有意にならないのが正しいはず。A vs Cでは、有意になるのが正しいはずです。

ということは、A vs Bでは50/1000の確率で、A vs Cでは70/1000の確率で、⁠まちがい」が起こることになります。

A vs Bでのまちがいのことを、統計用語で「αエラー」⁠2群の差がないのに、有意になってしまうまちがい)といいます。

また、A vs Cでのまちがいのことを、⁠βエラー」⁠2群の差があるのに有意にならないまちがい)といいます。

このようにまちがいが起こるのは、統計学の限界でもあります。特にαエラーは、5%で固定になります(P値の有意水準が5%であることと関係してます⁠⁠。

βエラーは、数式を使って理論的に計算することもできますし、今回のようにデータを発生させてみてシミュレーションすることもできます。シミュレーションを速く行うために、工夫をされている回答者もいました。

問4の解答は以下のとおりです。

hist(PvalAB, breaks=20)
hist(PvalAC, breaks=20)

sum(PvalAB  < 0.05) / 1000
sum(PvalAC  < 0.05) / 1000
  • PvalABは0.05未満(有意)が約5%、PvalACは約90%強。
  • A vs Bのαエラーは5%、A vs Cのβエラーは約10%弱であることがわかる(つまり100人サンプリングにおいて、A vs Cの身長差は、約10%の確率で有意とならない⁠⁠。
    A vs Bのβエラーと、A vs Cのαエラーは存在しない。

調査のコストを意識することが実務につながる

今回は、検定がどのようなものかを体感していただくために、Rを使う前提としました。

全体の値がわかれば、絶対まちがいは起こりません。しかし、サンプリングすることで測定を簡易にする代わりに、どうしてもある程度のまちがいが起こってしまいます。かといって、全体の値を測定するには費用がかかりすぎることがあります。

今回の場合、10万人のうち、たった100人(0.1%)を測定することで、A vs Bでは95%、A vs Cでは90%強で正しい推測を行えるのです。統計学を理解していれば、測定にコストのかかるビジネスシーンにおいて、全体調査を行うべきかサンプリング調査を行うべきかを、事前に判断することができ、コストカットや適切な予算見積もりにつながります。

おすすめ記事

記事・ニュース一覧