Octave でクロス集計・独立性の検定

# Octave でクロス集計・独立性の検定

クロス集計の場合は引数に長さの同じベクトルを 2 つ以上指定する。2 つのベクトルが指定された場合は 2 変数の独立性の検定を行う。

    usage:
    [t, chi2, p, labels] = crosstab(x, y)
    
    y は測定値ベクトル，g は測定値がどのグループのものかを示すベクトル
    戻り値を指定しない場合はクロス集計表を表示する
    戻り値を指定した場合は，後で変数を使用する（表示するなど）ことができる


## 使用例 1

クロス集計表を表示する。


```matlab
% statistics が必要
pkg load statistics

% 表示精度を高くする（任意）
format long
```

テストデータ

```matlab
x = [4;3;2;1;1;3;4;2;4;4;2;2;4;1;3;3;3;1;1;2;3;3;3;2;3;4;4;3;4;4];
y = ["c";"a";"b";"d";"d";"b";"a";"a";"a";"a";"c";"c";"a";"e";"a"
     "d";"d";"a";"d";"e";"c";"a";"a";"b";"a";"c";"a";"e";"c";"e"];
z = [1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2];
```


```matlab
crosstab(x, y)
```

    ans =
    
       1   0   0   3   1
       1   2   2   0   1
       5   1   1   2   1
       5   0   3   0   1
    


3 次元以上のクロス集計表を作ろうとすると，χ二乗検定は二次元クロス集計表の場合にのみ行われるとの警告がある（鬱陶しい）。


```matlab
crosstab(x, y, z)
```

    warning: crosstab: chi-square test only available for 2D results
    warning: called from
        crosstab at line 91 column 5
    
    ans =
    
    ans(:,:,1) =
    
       0   0   0   2   1
       1   1   2   0   0
       2   1   0   0   0
       4   0   1   0   0
    
    ans(:,:,2) =
    
       1   0   0   1   0
       0   1   0   0   1
       3   0   1   2   1
       1   0   2   0   1
    


## 使用例 2

結果を変数に代入し，後で使用する。変数名はどのように決めてもよいが，変数が何を表すかの順序は変えることができない。


```matlab
[t, chi2, p, labels] = crosstab(x, y);
t
chi2
p
labels
```

    t =
    
       1   0   0   3   1
       1   2   2   0   1
       5   1   1   2   1
       5   0   3   0   1
    
    chi2 = 18.14444444444444
    p = 0.111374562231808
    labels =
    {
      [1,1] = 1
      [2,1] = 2
      [3,1] = 3
      [4,1] = 4
      [5,1] = [](0x0)
      [1,2] = a
      [2,2] = b
      [3,2] = c
      [4,2] = d
      [5,2] = e
    }
    


自由度を計算して表示する。


```matlab
[nr, nc] = size(t);
df = (nr - 1) * (nc - 1);

printf("chisq = %.5g,  df = %d,  p value = %.5g\n", chi2, df, p)
```

    chisq = 18.144,  df = 12,  p value = 0.11137


必要のないものが後ろのほうにある場合には指定しないだけでよい。必要のないものが前のほうにある場合にはその場所に `~` を書けばよい。


```matlab
[~, chi2, p] = crosstab(x, y);
chi2
p
```

    chi2 = 18.14444444444444
    p = 0.111374562231808


表頭，表側，行和，列和を加えたクロス集計表を出力する。


```matlab
function print_table(table, labels, width=3)
    [nr, nc] = size(table);
    colsum = sum(table);
    rowsum = sum(table, 2);
    n = sum(table(:));

    % 二重クロス集計表を表示する
    % width = 3; % セルの幅（列名，行名，数値の桁数の最大値）
    printf("%*s", width+3, " ")
    for j = 1:nc
        printf("[%*s] ", width, labels{j, 2})
    end
    printf("[%*s]\n", width, "Sum")
    for i = 1:nr
        printf("[%*s]", width, labels{i, 1})
        for j = 1:nc
            printf("%*d ", width+2, table(i, j))
        end
        printf("%*d\n", width+2, rowsum(i))
    end
    printf("[%*s]", width, "Sum")
    for j = 1:nc
        printf("%*d ", width+2, colsum(j))
    end
    printf("%*d\n", width+2, n)
end
```


```matlab
[table, ~, ~, labels] = crosstab(x, y);
print_table(table, labels)
```

          [  a] [  b] [  c] [  d] [  e] [Sum]
    [  1]    1     0     0     3     1     5
    [  2]    1     2     2     0     1     6
    [  3]    5     1     1     2     1    10
    [  4]    5     0     3     0     1     9
    [Sum]   12     3     6     5     4    30


## 使用例 3

`crosstab(x, y)` は元データが必要である。

しかし，場合によっては二次元クロス集計表しかない（元データがない）こともある。そのような場合には，二次元クロス集計表からもとのデータを再現して `crosstab(x, y)` を使えばよい。

以下のプログラムは，二次元クロス集計表からデータを再現し，独立性の検定を行う。


```matlab
function [x, y, chisq, df, p] = crosstab2(table)
    [nr, nc] = size(table);
    x = zeros(nr * nc, 1);
    y = zeros(size(x));
    index = 0;
    for i = 1:nr
        for j = 1:nc
            for k = 1:table(i, j)
                index = index + 1;
                x(index) = i;
                y(index) = j;
            end
        end
    end
    [~, chisq, p] = crosstab(x, y);
    df = (nr - 1) * (nc - 1);
    printf("chisq = %.5g,  df = %d,  p value = %.5g\n", chisq, df, p)
end
```


```matlab
crosstab2([1 2; 3 4]);
```

    chisq = 0.079365,  df = 1,  p value = 0.77816



```matlab
tbl =  [5 2 0
        3 4 8
        1 3 9]
```

    tbl =
    
       5   2   0
       3   4   8
       1   3   9
    



```matlab
crosstab2(tbl);
```

    chisq = 12.196,  df = 4,  p value = 0.015949



```matlab
[x, y] = crosstab2(tbl);
```

    chisq = 12.196,  df = 4,  p value = 0.015949



```matlab
x'
```

    ans =
    
     Columns 1 through 20:
    
       1   1   1   1   1   1   1   2   2   2   2   2   2   2   2   2   2   2   2   2
    
     Columns 21 through 35:
    
       2   2   3   3   3   3   3   3   3   3   3   3   3   3   3
    



```matlab
y'
```

    ans =
    
     Columns 1 through 20:
    
       1   1   1   1   1   2   2   1   1   1   2   2   2   2   3   3   3   3   3   3
    
     Columns 21 through 35:
    
       3   3   1   2   2   2   3   3   3   3   3   3   3   3   3