File Coverage

blib/lib/Statistics/MVA/Bartlett.pm
Criterion Covered Total %
statement 21 84 25.0
branch 0 6 0.0
condition n/a
subroutine 7 13 53.8
pod 0 1 0.0
total 28 104 26.9


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__