line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Statistics::MVA::Bartlett; |
2
|
1
|
|
|
1
|
|
23967
|
use base Statistics::MVA; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
857
|
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
43001
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
27
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
19
|
|
6
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
46
|
|
7
|
1
|
|
|
1
|
|
898
|
use Math::Cephes qw(:explog); |
|
1
|
|
|
|
|
20830
|
|
|
1
|
|
|
|
|
384
|
|
8
|
1
|
|
|
1
|
|
1063
|
use Statistics::Distributions qw( chisqrdistr chisqrprob ); |
|
1
|
|
|
|
|
3581
|
|
|
1
|
|
|
|
|
89
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Statistics::MVA::Bartlett - Multivariate Test of Equality of Population Covariance Matrices. |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 VERSION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
This document describes Statistics::MVA::Bartlett version 0.0.4 |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=cut |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 SYNOPSIS |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# we have several groups of data each with 3 variables |
25
|
|
|
|
|
|
|
my $data_X = [ |
26
|
|
|
|
|
|
|
[qw/ 191 131 53/], |
27
|
|
|
|
|
|
|
[qw/ 200 137 52/], |
28
|
|
|
|
|
|
|
[qw/ 173 127 50/], |
29
|
|
|
|
|
|
|
[qw/ 160 118 47/], |
30
|
|
|
|
|
|
|
[qw/ 188 134 54/], |
31
|
|
|
|
|
|
|
[qw/ 186 129 51/], |
32
|
|
|
|
|
|
|
[qw/ 163 115 47/], |
33
|
|
|
|
|
|
|
]; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $data_Y = [ |
36
|
|
|
|
|
|
|
[qw/ 211 122 49/], |
37
|
|
|
|
|
|
|
[qw/ 201 144 47/], |
38
|
|
|
|
|
|
|
[qw/ 242 131 54/], |
39
|
|
|
|
|
|
|
[qw/ 184 108 43/], |
40
|
|
|
|
|
|
|
[qw/ 223 127 51/], |
41
|
|
|
|
|
|
|
[qw/ 208 125 50/], |
42
|
|
|
|
|
|
|
[qw/ 199 124 46/], |
43
|
|
|
|
|
|
|
]; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my $data_Z = [ |
46
|
|
|
|
|
|
|
[qw/ 185 134 50/], |
47
|
|
|
|
|
|
|
[qw/ 171 128 49/], |
48
|
|
|
|
|
|
|
[qw/ 174 131 52/], |
49
|
|
|
|
|
|
|
[qw/ 186 107 49/], |
50
|
|
|
|
|
|
|
[qw/ 211 118 51/], |
51
|
|
|
|
|
|
|
[qw/ 217 122 49/], |
52
|
|
|
|
|
|
|
]; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
use Statistics::MVA::Bartlett; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Create a Statistics::MVA::Bartlett object and pass it the data as a series of Lists-of-Lists within an anonymous array. |
57
|
|
|
|
|
|
|
my $bart1 = Statistics::MVA::Bartlett->new([$data_X, $data_Y, $data_Z]); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Access the output using the bartlett_mva method. In void context it prints a report to STDOUT. |
60
|
|
|
|
|
|
|
$bart->bartlett_mva; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# In LIST-context it returns the relevant parameters. |
63
|
|
|
|
|
|
|
my ($chi, $df, $p) = $bart->bartlett_mva; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 DESCRIPTION |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Bartlett's test is used to test if k samples have equal variances. This multivariate form |
70
|
|
|
|
|
|
|
tests for homogeneity of the variance-covariance matrices across samples. Some statistical tests assume such homogeneity |
71
|
|
|
|
|
|
|
across groups or samples. This test allows you to check that assumption. See |
72
|
|
|
|
|
|
|
http://www.itl.nist.gov/div898/handbook/eda/section3/eda357.htm. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
1
|
|
|
1
|
|
9
|
use version; our $VERSION = qv('0.0.4'); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
9
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub bartlett_mva { |
79
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
80
|
0
|
|
|
|
|
|
my $context = wantarray; |
81
|
0
|
|
|
|
|
|
my $s_ref = $self->[0]; |
82
|
0
|
|
|
|
|
|
my $k = $self->[1]; |
83
|
0
|
|
|
|
|
|
my $p = $self->[2]; |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
my $c_ref = &_Cs($s_ref, $k, $p); |
86
|
0
|
|
|
|
|
|
my $d_ref = &_dets($c_ref, $k); |
87
|
0
|
|
|
|
|
|
my $chi = &_final($d_ref, $k, $p); |
88
|
0
|
|
|
|
|
|
my $df = $p*($p+1)*($k-1)/2; |
89
|
0
|
|
|
|
|
|
my $chisprob = &chisqrprob($df,$chi); |
90
|
|
|
|
|
|
|
|
91
|
0
|
0
|
|
|
|
|
if ( !$context ) { print qq{\nChi = $chi, df = $df and p = $chisprob}; return; } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
else { return ($chi, $df, $chisprob); } |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub _dets { |
96
|
0
|
|
|
0
|
|
|
my ($c_ref, $k) = @_; |
97
|
|
|
|
|
|
|
# d<-det(c) # d_a<-det(c_a) # d_b<-det(c_b) |
98
|
0
|
|
|
|
|
|
my $det_ref = []; |
99
|
0
|
|
|
|
|
|
for my $i (0..$k) { |
100
|
0
|
|
|
|
|
|
my $determinant = $c_ref->[$i][0]->det; |
101
|
0
|
|
|
|
|
|
$det_ref->[$i] = [$determinant, $c_ref->[$i][1]]; |
102
|
|
|
|
|
|
|
} |
103
|
0
|
|
|
|
|
|
return $det_ref; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub _final { |
107
|
0
|
|
|
0
|
|
|
my ($d_ref, $k, $p) = @_; |
108
|
0
|
|
|
|
|
|
my $d = ( ( $d_ref->[$k][1] - $k ) * ( log ( $d_ref->[$k][0] ) ) ); |
109
|
0
|
|
|
|
|
|
my $d_sum = 0; |
110
|
0
|
|
|
|
|
|
for my $i (0..$k-1) { $d_sum += ( ( $d_ref->[$i][1] - 1 ) * ( log ( $d_ref->[$i][0] ) ) ); } |
|
0
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
my $m = $d - $d_sum; |
112
|
0
|
|
|
|
|
|
my $n_sum = 0; |
113
|
0
|
|
|
|
|
|
for my $i (0..$k-1) { $n_sum += 1 / ( $d_ref->[$i][1] - 1 ); } # print 1/($d_ref->[$i][1]-1) } |
|
0
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
my $h = 1 - ( ( 2 * $p* $p+3 * $p-1 ) / (6 * ($p+1) * ($k-1) ) * ( $n_sum - (1/($d_ref->[$k][1]-$k))) ); |
115
|
0
|
|
|
|
|
|
my $chi = $m * $h; |
116
|
0
|
|
|
|
|
|
return $chi; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub _Cs { |
120
|
0
|
|
|
0
|
|
|
my ( $s_ref, $k, $p ) = @_; |
121
|
0
|
|
|
|
|
|
my $c_ref = []; |
122
|
|
|
|
|
|
|
#/ matrices are initialised as zero! so we can just use addition... and not shadow or initialise a p*p structure of 0s |
123
|
0
|
|
|
|
|
|
my $c_total = Math::MatrixReal->new($p, $p); |
124
|
|
|
|
|
|
|
# $new_matrix = $some_matrix->shadow(); |
125
|
0
|
|
|
|
|
|
my $n_total = 0; |
126
|
0
|
|
|
|
|
|
for my $i (0..$k-1) { |
127
|
0
|
|
|
|
|
|
my $c_mat = Math::MatrixReal->new($p, $p); |
128
|
0
|
|
|
|
|
|
my $factor = (1/($s_ref->[$i][1]-1)); |
129
|
0
|
|
|
|
|
|
$c_mat->multiply_scalar($s_ref->[$i][0],$factor); |
130
|
0
|
|
|
|
|
|
$c_total->add($c_total,$s_ref->[$i][0]); |
131
|
0
|
|
|
|
|
|
$n_total += $s_ref->[$i][1]; |
132
|
0
|
|
|
|
|
|
$c_ref->[$i] = [$c_mat, $s_ref->[$i][1]]; |
133
|
|
|
|
|
|
|
} |
134
|
0
|
|
|
|
|
|
my $factor = (1/($n_total-$k)); |
135
|
0
|
|
|
|
|
|
$c_total->multiply_scalar($c_total,$factor); |
136
|
0
|
|
|
|
|
|
$c_ref->[$k] = [$c_total,$n_total]; |
137
|
0
|
|
|
|
|
|
return $c_ref; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub _cv_matrices { |
141
|
0
|
|
|
0
|
|
|
my ( $groups, $k ) = @_; |
142
|
0
|
|
|
|
|
|
my @p; |
143
|
0
|
|
|
|
|
|
my $a_ref = []; |
144
|
|
|
|
|
|
|
#for my $i (0..$self->[1]-1) { |
145
|
0
|
|
|
|
|
|
for my $i (0..$k-1) { |
146
|
|
|
|
|
|
|
#my $mva = Statistics::MVA->new($groups->[$i],{standardise => 0, divisor => 1}); |
147
|
0
|
|
|
|
|
|
my $mva = Statistics::MVA->new($groups->[$i]); |
148
|
0
|
|
|
|
|
|
my $mva_matrix = my $a = Math::MatrixReal->new_from_rows($mva->[0]); |
149
|
0
|
|
|
|
|
|
push @p, $mva->[1]; |
150
|
0
|
|
|
|
|
|
$a_ref->[$i] = [ $mva_matrix, $mva->[2] ]; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
#/ should make sure than p for all entries is the same!!! |
153
|
0
|
|
|
|
|
|
my $p_check = shift @p; |
154
|
0
|
0
|
|
|
|
|
croak qq{\nAll groups must have the same variable number} if &_p_notall($p_check, \@p); |
155
|
|
|
|
|
|
|
#croak qq{\nAll groups must have the same variable number} if &_p_notall(@p); |
156
|
0
|
|
|
|
|
|
return ($a_ref, $p_check); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub _p_notall { |
160
|
0
|
|
|
0
|
|
|
my ($p_check, $p_ref) = @_; |
161
|
|
|
|
|
|
|
#for (@p) { |
162
|
0
|
|
|
|
|
|
for (@{$p_ref}) { |
|
0
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# return 0 if $_ != $p_check; |
164
|
0
|
0
|
|
|
|
|
return 1 if $_ != $p_check; |
165
|
|
|
|
|
|
|
} |
166
|
0
|
|
|
|
|
|
return 0; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
1; # Magic true value required at end of module |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
__END__ |