About connecting the dots.

data science related trivial things

Box-Cox変換で変数を正規分布に近づける

よくある問題

実データを使って分析するときによくあるのが,すっごく偏った分布のデータで,正規性を仮定した分析を行いたいという状況です.具体的には,回帰分析の独立変数に年収とかを使う場合なんかです.回帰分析だと,独立変数が正規分布をしていないと正しく係数や有意性の推定を行えないことがあります*1

Box-Cox変換

そんなときに役立つのが,データを正規分布に近づけてくれるBox-Cox変換という手法です.具体的な数式は以下の通り*2.偏った分布を持つxを正規分布に近づけるようなλを推定しましょう,という話なわけです.

\left\{\frac{1}{\lambda}(x^\lambda-1), \lambda\neq0 \\ log(x), \lambda=0

Rでこれを行うには,{car}パッケージにあるpowerTransform関数を使います*3*4.データはヘルプの例にも出ているWool$cyclesを使います.このデータについては,めっちゃ分布が右に偏ってますね.

> install.packages("car")
> library(car)

> hist(Wool$cycle)

f:id:SAM:20130622111236j:plain

そこでこの変数に,powerTransformをかけてλを推定し,それをもとにbcPowerで変換をかけた値を取得します.そうすると,もとの分布の左寄りの部分が修正されて,正規性を持った分布になったことがみてとれるかと思います.

> summary(p1 <- powerTransform(Wool$cycles))

bcPower Transformation to Normality 

            Est.Power Std.Err. Wald Lower Bound Wald Upper Bound
Wool$cycles   -0.0473   0.1931          -0.4259           0.3313

Likelihood ratio tests about transformation parameters
                              LRT df         pval
LR test, lambda = (0)  0.05994796  1 8.065782e-01
LR test, lambda = (1) 27.29886008  1 1.743141e-07

hist(bcPower(Wool$cycles, p1$roundlam))

f:id:SAM:20130622111246j:plain

注意点

λの扱い

ぱっと簡単な例をあげましたが,このλの値について,推定値をそのまま入れこむみたいなことはせず,切りのいい数字にしてしまった上で(上記の例でいえば-0.1とか)変換をかけることが多いです.それはデータに過剰フィットしている可能性の高い値よりも,(恣意的な部分があるかもしれませんが)解釈可能性がより高い値の方が,実用上はるかに有用だからです.

0以下の値への対応

また,数式をみればわかる通り,この変換は変数に0や負の値が含まれている場合はうまく推定できません.そのようなときは,変数が0以下にならないように,一定の値を加算した上で変換をかける,といったやり方が良くされます.ただしこの加算する値によって推定結果や変換結果,ひいては分析の結果が変わってくるので,注意深くデータをみた上で決定する必要があります*5

というわけで,これで楽しく回帰分析できますね,というお話です.今日はこれまで.

*1:なお,従属変数が偏っている場合には,ポアソン回帰やロジスティック回帰回帰など,正規分布以外の分布関数を仮定したモデルを使います.Box-Cox変換を従属変数に使って無理矢理重回帰をするのはよくありません.

*2:λが0の場合の形は,上側の式でλ=0のときに収束するのがこの形だから,ということだそうです.

*3:box.cox.powers関数は既にdeprecatedになっているようです.

*4:新しいpowerTransformでは,Box-Cox変換をより一般化しているそうです.powerTransform(cycles ~ len + amp + load, Wool)のように一般線形モデルの形で独立変数群を同時に指定することで,与えられた独立変数群の予測値に対して従属変数の残差が細小になるようにcyclesを正規変換してくれるλを推定するそうです.後の注意点にもあげているように,私個人としてはそのような使い方には否定的ですが...

*5:私自身は,この手の変換については,おおむね非負の値について,1をプラスする,という以上のことはやらないです.面倒だし解釈しにくいので.