File Coverage

blib/lib/Statistics/ChisqIndep.pm
Criterion Covered Total %
statement 97 106 91.5
branch 13 26 50.0
condition 2 6 33.3
subroutine 8 9 88.8
pod 0 4 0.0
total 120 151 79.4


line stmt bran cond sub pod time code
1             package Statistics::ChisqIndep;
2              
3 1     1   514 use strict;
  1         2  
  1         39  
4 1     1   5 use vars qw ($VERSION $AUTOLOAD);
  1         1  
  1         61  
5 1     1   5 use Carp;
  1         5  
  1         93  
6 1     1   1998 use Statistics::Distributions qw (chisqrprob);
  1         3138  
  1         1114  
7              
8             my %fields = (obs => [],
9             expected => [],
10             rows => 0,
11             cols => 0,
12             df => 0,
13             total => 0,
14             rtotals => [],
15             ctotals => [],
16             chisq_statistic => 0,
17             p_value => 0,
18             valid => 0,
19             warning => 0);
20             $VERSION = '0.1';
21              
22             sub new {
23 1     1 0 17 my $proto = shift;
24 1   33     7 my $class = ref($proto) || $proto;
25 1         11 my $self= {%fields};
26 1         4 bless($self,$class);
27 1         4 return $self;
28             }
29              
30             sub load_data {
31 1     1 0 7 my $self = shift;
32 1         6 $self->{valid} = 0;
33 1         3 $self->{obs} = shift;
34 1         2 my @obs = @{$self->{obs}};
  1         3  
35 1         3 my $exp;
36 1         2 my $rows = scalar(@obs);
37 1 50       4 return if $rows < 2;
38 1         2 my $cols = scalar(@{$obs[0]});
  1         7  
39 1 50       5 return if $cols < 2;
40 1         2 my @rtotals;
41             my @ctotals;
42 1         2 my $total = 0;
43 1         1 my $df = 0;
44 1         2 my $chisq = 0;
45 1         1 my $chiprob = 0;
46 1         5 for (my $i = 0; $i < $rows; $i++) {
47 2         2 my $c = scalar(@{$obs[$i]});
  2         3  
48 2 50       5 return if $c != $cols;
49 2         7 for (my $j = 0; $j < $cols; $j++) {
50 6 100       14 $rtotals[$i] = 0 if (!defined($rtotals[$i]));
51 6 100       16 $ctotals[$j] = 0 if (!defined($ctotals[$j]));
52 6         7 $rtotals[$i] += $obs[$i]->[$j];
53 6         8 $ctotals[$j] += $obs[$i]->[$j];
54 6         10 $total += $obs[$i]->[$j];
55 6 100       23 $self->{warning} = 1 if $obs[$i]->[$j] < 25;
56             }
57             }
58 1 50       3 return if ($total < 0);
59              
60              
61             #compute the expected values for each cell
62 1         4 for (my $i = 0; $i < $rows; $i++) {
63 2         5 for (my $j = 0; $j < $cols; $j++) {
64 6 50 33     24 if ($rtotals[$i] == 0 || $ctotals[$j] == 0) {
65 0         0 $exp->[$i]->[$j] = 0
66             } else {
67 6         15 $exp->[$i]->[$j] = $rtotals[$i] * $ctotals[$j] / $total;
68 6         46 $chisq += ($obs[$i]->[$j] - $exp->[$i]->[$j])**2 /$exp->[$i]->[$j];
69             }
70             }
71             }
72            
73 1         2 $df = ($rows - 1) * ($cols - 1);
74 1         7 $chiprob = chisqrprob($df, $chisq);
75              
76             #update the global fields
77 1         99 $self->{expected} = $exp;
78 1         2 $self->{rows} = $rows;
79 1         2 $self->{cols} = $cols;
80 1         3 $self->{df} = $df;
81 1         2 $self->{total} = $total;
82 1         3 $self->{rtotals} = \@rtotals;
83 1         3 $self->{ctotals} = \@ctotals;
84 1         2 $self->{chisq_statistic} = $chisq;
85 1         3 $self->{p_value} = $chiprob;
86 1         2 $self->{valid} = 1;
87            
88 1         16 return 1;
89             }
90              
91             sub print_contingency_table {
92 1     1 0 2 my $self = shift;
93 1         3 my $rows = $self->{rows};
94 1         3 my $cols = $self->{cols};
95 1         2 my $obs = $self->{obs};
96 1         2 my $exp = $self->{expected};
97 1         3 my $rtotals = $self->{rtotals};
98 1         3 my $ctotals = $self->{ctotals};
99 1         2 my $total = $self->{total};
100            
101 1         5 for (my $j = 0; $j < $cols; $j++) {
102 3         12 print "\t",$j + 1;
103             }
104 1         3 print "\trtotal\n";
105 1         5 for (my $i = 0; $i < $rows; $i ++) {
106 2         14 print $i + 1, "\t";
107 2         13 for(my $j = 0 ; $j < $cols; $j ++) {
108 6         20 print $obs->[$i]->[$j], "\t";
109             }
110 2         5 print $rtotals->[$i], "\n";
111 2         3 print "\t";
112 2         16 for(my $j = 0 ; $j < $cols; $j ++) {
113 6         46 printf "(%.2f)\t", $exp->[$i]->[$j];
114             }
115 2         7 print "\n";
116             }
117 1         3 print "ctotal\t";
118 1         5 for (my $j = 0; $j < $cols; $j++) {
119 3         14 print $ctotals->[$j], "\t";
120             }
121 1         0 print $total, "\n";
122             }
123              
124             sub print_summary {
125 1     1 0 7 my $self = shift;
126 1 50       4 if($self->{valid}) {
127 1         22 print "Rows: ", $self->{rows}, "\n";
128 1         4 print "Columns: ", $self->{cols}, "\n";
129 1         27 print "Degree of Freedom: ", $self->{df}, "\n";
130 1         3 print "Total Count: ", $self->{total}, "\n";
131 1         7 print "Chi-square Statistic: ", $self->{chisq_statistic}, "\n";
132 1         3 print "p-value: ", $self->{p_value}, "\n";
133 1 50       6 print "Warning: some of the cell counts might be too low. \n" if ($self->{warning});
134 1         5 $self->print_contingency_table();
135             }
136             }
137              
138             sub AUTOLOAD {
139 0     0     my $self = shift;
140 0 0         my $type = ref($self)
141             or croak "$self is not an object";
142 0           my $name = $AUTOLOAD;
143 0           $name =~ s/.*://; ##Strip fully qualified-package portion
144 0 0         return if $name eq "DESTROY";
145 0 0         unless (exists $self->{$name} ) {
146 0           croak "Can't access `$name' field in class $type";
147             }
148             ##Read only method
149 0           return $self->{$name};
150             }
151              
152             1;
153             __END__