大波の検定、小波の検定を実装してみた

2つの変数が正規分布に従っていない時や、外れ値の影響を無視することが出来無い時に、相関を調べる手法として、大波の検定や小波の検定がある。これらを用いると、外れ値等の影響を受けにくいという利点がある。
これらは、符号検定という考え方に基づいて行われている。

  • 大波の検定

各群のメジアンを求め、各変数に対して大きい数の時は+符号を、小さい時はー符号をつける。各群に付けられた符号を掛けて、符号が少ない方の数を用いて、符号検定に基づいて検定を行う。

符号を求める時に直前の値より、大きい時は+符号を、小さい時はー符号をつける。その後は、大波の検定と同様にして検定する。

検定には、R言語に標準で組み込まれているdata(cars)を使用した。

#!/usr/bin/python
# coding: UTF-8
import numpy
class codetest:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def times(self,x,y):
        """
        リストx,yの積を返す
        """
        seki = []
        if len(x) == len(y):
            for i in range(len(x)):
                seki.append(x[i] * y[i])
        else:
            print "要素の数が違います"
        return seki

    def level(self,n):
        k = [1.2879,0.9800]
        p = ["0.01","0.05"]
        rlt = {}
        for i in range(2):
            m1 = (n-1)/float(2)
            m2 = k[i] * numpy.sqrt(n-1)
            ans = int(m1-m2)
            rlt.update([(p[i],ans)])
        return rlt

    def oonami_hugou(self,x):
        """
        大波の検定用の符号を返す
        """
        pm = []
        for i in x:
            if numpy.median(x) < i:
                pm.append(1)
            elif numpy.median(x) > i:
                pm.append(-1)
            else:
                pm.append(0)
        return pm

    def konami_hugou(self,x):
        pm = []
        for i in range(1,len(x)):
            if x[i-1] < x[i]:
                pm.append(1)
            elif x[i-1] < x[i]: 
                pm.append(-1)
            else:
                pm.append(0)
        return pm

    def test(self,n,less):
        level = self.level(n)
        if level['0.01'] >= less :
            return str("有意水準が1%の時,有意である.")
        elif level['0.05'] >= less:
            return "有意水準が5%の時,有意である."
        else:
            return "有意でない."

    def oonami(self):
        xh = self.oonami_hugou(self.x)
        yh = self.oonami_hugou(self.y)
        seki = self.times(xh,yh)
        if seki.count(1) > seki.count(-1):
            return self.test(len(x),seki.count(-1))
        else:
            return self.test(len(x),seki.count(1))
    
    def konami(self):
        xh = self.konami_hugou(self.x)
        yh = self.konami_hugou(self.y)
        seki = self.times(xh,yh)
        if seki.count(1) > seki.count(-1):
            return self.test(len(x),seki.count(-1))
        else:
            return self.test(len(x),seki.count(1))

x = [4,4,7,7,8,9,10,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,16,16,17,17,17,18,18,18,18,19,19,19,20,20,20,20,20,22,23,24,24,24,24,25]

y = [2,10,4,22,16,10,18,26,34,17,28,14,20,24,28,26,34,34,46,26,36,60,80,20,26,54,32,40,32,40,50,42,56,76,84,36,46,68,32,48,52,56,64,66,54,70,92,93,120,85]

t = codetest(x,y)
print t.oonami()
print t.konami()

実行結果は、

有意水準が1%の時,有意である.
有意水準が1%の時,有意である.

である。