Skip to content

Commit 88049d3

Browse files
committed
error for anova with too few samples for experiment
1 parent b524b77 commit 88049d3

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- fix anova_design_matrix for between-subject >2 values (rest of RT#97925)
77
- add demo
88
- remove filt_exp and filt_ma, deprecated in 2011
9+
- now an exception to give anova n-observations <= product of categories in IVs
910

1011
0.853 2025-01-03
1112
- uses PDL 2.096+ lib/*.pd format for quicker builds

lib/PDL/Stats/GLM.pd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ sub PDL::anova_rptd {
10561056
# highest ord inter for purely within design, (p-1)*(q-1)*(n-1)
10571057
my $factor = (ref $full[-1] ? $full[-1] : $err_ref->[$full[-1]])->dim(1);
10581058
my $df = $ret{ "$i_pref$e df" } = $factor * $within_df;
1059+
die "${i_pref}residual df = 0" if $df <= 0;
10591060
$ret{ "$i_pref$e ms" } = $ret{ "$i_pref$e ss" } / $df;
10601061
} elsif (ref $full[$k]) { # unique error term
10611062
next EFFECT
@@ -1066,13 +1067,15 @@ sub PDL::anova_rptd {
10661067
= $y->sse(sumover($b_G * $G->transpose)) - $ret{ss_residual};
10671068
if ($k != $#full) {
10681069
my $df = $ret{"$i_pref$e df"} = $full[$k]->dim(1);
1070+
die "residual df = 0" if $df <= 0;
10691071
$ret{"$i_pref$e ms"} = $ss / $df;
10701072
}
10711073
} else { # repeating error term
10721074
my $ss = $ret{$k == $#full ? 'ss_subject' : "$i_pref$e ss"}
10731075
= $ret{"| $idv->[$full[$k]] |$e ss"};
10741076
if ($k != $#full) {
10751077
my $df = $ret{"$i_pref$e df"} = $ret{"| $idv->[$full[$k]] |$e df"};
1078+
die "residual df = 0" if $df <= 0;
10761079
$ret{"$i_pref$e ms"} = $ss / $df;
10771080
}
10781081
}
@@ -1095,6 +1098,7 @@ sub PDL::anova_rptd {
10951098
= $y->sse( sumover($b_G * $G->transpose) ) - $ret{ss_residual};
10961099
my $df0 = $ret{ "| $idv->[$k] | df" } = $ivs_ref->[$k]->dim(1);
10971100
$ret{ "| $idv->[$k] || err df" } = $df1;
1101+
die "residual df = 0" if $df1 <= 0;
10981102
$ret{ "| $idv->[$k] | ms" } = $ret{ "| $idv->[$k] | ss" } / $df0;
10991103
}
11001104
}

t/glm.t

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,15 @@ is_pdl $b_bad->dvrs(ones(6) * .5), pdl( 'BAD -1.17741002251547 -1.17741002251547
394394
';
395395
}
396396

397+
{ # anova with too few samples for experiment (3*2*2 categories, 12 samples)
398+
my $y = pdl '[1 1 2 2 3 3 3 3 4 5 5 5]'; # ratings for 12 apples
399+
my $a = sequence(12) % 3 + 1; # IV for types of apple
400+
my @b = qw( y y y y y y n n n n n n ); # IV for whether we baked the apple
401+
my @c = qw( r g r g r g r g r g r g ); # IV for apple colour (red/green)
402+
eval {$y->anova( $a, \@b, \@c, { IVNM=>[qw(apple bake colour)], PLOT=>0 } )};
403+
like $@, qr/residual df = 0/, 'error when too few sample';
404+
}
405+
397406
{ # anova 1 way
398407
my $d = pdl qw( 3 2 1 5 2 1 5 3 1 4 1 2 3 5 5 );
399408
my $a = qsort sequence(15) % 3;

0 commit comments

Comments
 (0)