Added remaining calculations for the separate variance contrast tests
[pspp-builds.git] / src / oneway.q
1 /* PSPP - One way ANOVA. -*-c-*-
2
3    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4    Author: John Darrington 2004
5
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA. */
20
21 #include <config.h>
22 #include <gsl/gsl_cdf.h>
23 #include "error.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include "alloc.h"
28 #include "str.h"
29 #include "case.h"
30 #include "command.h"
31 #include "lexer.h"
32 #include "error.h"
33 #include "magic.h"
34 #include "misc.h"
35 #include "tab.h"
36 #include "som.h"
37 #include "value-labels.h"
38 #include "var.h"
39 #include "vfm.h"
40 #include "hash.h"
41 #include "casefile.h"
42 #include "oneway.h"
43 #include "group.h"
44 #include "levene.h"
45
46 /* (specification)
47    "ONEWAY" (oneway_):
48      *variables=custom;
49      +missing=miss:!analysis/listwise,
50              incl:include/!exclude;
51      contrast= double list;
52      statistics[st_]=descriptives,homogeneity.
53 */
54 /* (declarations) */
55 /* (functions) */
56
57
58
59 static int bad_weight_warn = 1;
60
61
62 static struct cmd_oneway cmd;
63
64 /* The independent variable */
65 static struct variable *indep_var;
66
67 /* Number of dependent variables */
68 static int n_vars;
69
70 /* The dependent variables */
71 static struct variable **vars;
72
73
74 /* A  hash table containing all the distinct values of the independent
75    variables */
76 static struct hsh_table *global_group_hash ;
77
78 /* The number of distinct values of the independent variable, when all 
79    missing values are disregarded */
80 static int ostensible_number_of_groups=-1;
81
82
83 /* Function to use for testing for missing values */
84 static is_missing_func value_is_missing;
85
86
87 static void calculate(const struct casefile *cf, void *_mode);
88
89
90 /* Routines to show the output tables */
91 static void show_anova_table(void);
92 static void show_descriptives(void);
93 static void show_homogeneity(void);
94 static void show_contrast_coeffs(void);
95 static void show_contrast_tests(void);
96
97
98
99 int
100 cmd_oneway(void)
101 {
102   int i;
103
104   if ( !parse_oneway(&cmd) )
105     return CMD_FAILURE;
106
107   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
108   if (cmd.incl == ONEWAY_INCLUDE ) 
109     value_is_missing = is_system_missing;
110   else
111     value_is_missing = is_missing;
112
113   multipass_procedure_with_splits (calculate, &cmd);
114
115   /* Check the sanity of the given contrast values */
116   for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
117     {
118       int j;
119       double sum = 0;
120
121       if ( subc_list_double_count(&cmd.dl_contrast[i]) != 
122            ostensible_number_of_groups )
123         {
124           msg(SE, 
125               _("Number of contrast coefficients must equal the number of groups"));
126           return CMD_FAILURE;
127         }
128
129       for (j=0; j < ostensible_number_of_groups ; ++j )
130         sum += subc_list_double_at(&cmd.dl_contrast[i],j);
131
132       if ( sum != 0.0 ) 
133         msg(SW,_("Coefficients for contrast %d do not total zero"),i + 1);
134     }
135
136
137
138   /* Show the statistics tables */
139   if ( cmd.sbc_statistics ) 
140     {
141     for (i = 0 ; i < ONEWAY_ST_count ; ++i ) 
142       {
143         if  ( ! cmd.a_statistics[i]  ) continue;
144
145         switch (i) {
146         case ONEWAY_ST_DESCRIPTIVES:
147           show_descriptives();
148           break;
149         case ONEWAY_ST_HOMOGENEITY:
150           show_homogeneity();
151           break;
152         }
153       }
154   }
155
156
157   show_anova_table();
158      
159   if (cmd.sbc_contrast)
160     {
161       show_contrast_coeffs();
162       show_contrast_tests();
163     }
164
165
166   /* Clean up */
167   for (i = 0 ; i < n_vars ; ++i ) 
168     {
169       struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
170
171       hsh_destroy(group_hash);
172     }
173
174   hsh_destroy(global_group_hash);
175
176   return CMD_SUCCESS;
177 }
178
179
180
181
182
183 /* Parser for the variables sub command */
184 static int
185 oneway_custom_variables(struct cmd_oneway *cmd UNUSED)
186 {
187
188   lex_match('=');
189
190   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
191       && token != T_ALL)
192     return 2;
193   
194
195   if (!parse_variables (default_dict, &vars, &n_vars,
196                         PV_DUPLICATE 
197                         | PV_NUMERIC | PV_NO_SCRATCH) )
198     {
199       free (vars);
200       return 0;
201     }
202
203   assert(n_vars);
204
205   if ( ! lex_match(T_BY))
206     return 2;
207
208
209   indep_var = parse_variable();
210
211   if ( !indep_var ) 
212     {
213       msg(SE,_("`%s' is not a variable name"),tokid);
214       return 0;
215     }
216
217
218   return 1;
219 }
220
221
222 /* Show the ANOVA table */
223 static void  
224 show_anova_table(void)
225 {
226   int i;
227   int n_cols =7;
228   int n_rows = n_vars * 3 + 1;
229
230   struct tab_table *t;
231
232
233   t = tab_create (n_cols,n_rows,0);
234   tab_headers (t, 2, 0, 1, 0);
235   tab_dim (t, tab_natural_dimensions);
236
237
238   tab_box (t, 
239            TAL_2, TAL_2,
240            -1, TAL_1,
241            0, 0,
242            n_cols - 1, n_rows - 1);
243
244   tab_hline (t, TAL_2, 0, n_cols - 1, 1 );
245   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
246   tab_vline (t, TAL_0, 1, 0, 0);
247   
248   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares"));
249   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
250   tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
251   tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
252   tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
253
254
255   for ( i=0 ; i < n_vars ; ++i ) 
256     {
257       struct group_statistics *totals = &vars[i]->p.ww.ugs;
258       struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
259       struct hsh_iterator g;
260       struct group_statistics *gs;
261       double ssa=0;
262
263
264       for (gs =  hsh_first (group_hash,&g); 
265            gs != 0; 
266            gs = hsh_next(group_hash,&g))
267        {
268          ssa += (gs->sum * gs->sum)/gs->n;
269        }
270       
271       ssa -= ( totals->sum * totals->sum ) / totals->n ;
272
273       const char *s = (vars[i]->label) ? vars[i]->label : vars[i]->name;
274
275
276       tab_text (t, 0, i * 3 + 1, TAB_LEFT | TAT_TITLE, s);
277       tab_text (t, 1, i * 3 + 1, TAB_LEFT | TAT_TITLE, _("Between Groups"));
278       tab_text (t, 1, i * 3 + 2, TAB_LEFT | TAT_TITLE, _("Within Groups"));
279       tab_text (t, 1, i * 3 + 3, TAB_LEFT | TAT_TITLE, _("Total"));
280       
281       if (i > 0)
282         tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1);
283
284       {
285         const double sst = totals->ssq - ( totals->sum * totals->sum) / totals->n ;
286         const double df1 = vars[i]->p.ww.n_groups - 1;
287         const double df2 = totals->n - vars[i]->p.ww.n_groups ;
288         const double msa = ssa / df1;
289         
290         vars[i]->p.ww.mse  = (sst - ssa) / df2;
291         
292         
293         /* Sums of Squares */
294         tab_float (t, 2, i * 3 + 1, 0, ssa, 10, 2);
295         tab_float (t, 2, i * 3 + 3, 0, sst, 10, 2);
296         tab_float (t, 2, i * 3 + 2, 0, sst - ssa, 10, 2);
297
298
299         /* Degrees of freedom */
300         tab_float (t, 3, i * 3 + 1, 0, df1, 4, 0);
301         tab_float (t, 3, i * 3 + 2, 0, df2, 4, 0);
302         tab_float (t, 3, i * 3 + 3, 0, totals->n - 1, 4, 0);
303
304         /* Mean Squares */
305         tab_float (t, 4, i * 3 + 1, TAB_RIGHT, msa, 8, 3);
306         tab_float (t, 4, i * 3 + 2, TAB_RIGHT, vars[i]->p.ww.mse, 8, 3);
307         
308
309         { 
310           const double F = msa/vars[i]->p.ww.mse ;
311
312           /* The F value */
313           tab_float (t, 5, i * 3 + 1, 0,  F, 8, 3);
314         
315           /* The significance */
316           tab_float (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
317         }
318
319       }
320
321     }
322
323
324   tab_title (t, 0, _("ANOVA"));
325   tab_submit (t);
326
327
328 }
329
330 /* Show the descriptives table */
331 static void  
332 show_descriptives(void)
333 {
334   int v;
335   int n_cols =10;
336   struct tab_table *t;
337   int row;
338
339   const double confidence=0.95;
340   const double q = (1.0 - confidence) / 2.0;
341
342   
343   int n_rows = 2 ; 
344
345
346
347   for ( v = 0 ; v < n_vars ; ++v ) 
348     n_rows += vars[v]->p.ww.n_groups + 1;
349
350   t = tab_create (n_cols,n_rows,0);
351   tab_headers (t, 2, 0, 2, 0);
352   tab_dim (t, tab_natural_dimensions);
353
354
355   /* Put a frame around the entire box, and vertical lines inside */
356   tab_box (t, 
357            TAL_2, TAL_2,
358            -1, TAL_1,
359            0, 0,
360            n_cols - 1, n_rows - 1);
361
362   /* Underline headers */
363   tab_hline (t, TAL_2, 0, n_cols - 1, 2 );
364   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
365   
366   tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("N"));
367   tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Mean"));
368   tab_text (t, 4, 1, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
369   tab_text (t, 5, 1, TAB_CENTER | TAT_TITLE, _("Std. Error"));
370
371
372   tab_vline(t, TAL_0, 7, 0, 0);
373   tab_hline(t, TAL_1, 6, 7, 1);
374   tab_joint_text (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF, _("%g%% Confidence Interval for Mean"),confidence*100.0);
375
376   tab_text (t, 6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound"));
377   tab_text (t, 7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound"));
378
379   tab_text (t, 8, 1, TAB_CENTER | TAT_TITLE, _("Minimum"));
380   tab_text (t, 9, 1, TAB_CENTER | TAT_TITLE, _("Maximum"));
381
382
383   tab_title (t, 0, _("Descriptives"));
384
385
386   row = 2;
387   for ( v=0 ; v < n_vars ; ++v ) 
388     {
389       double T;
390       double std_error;
391
392
393       struct hsh_iterator g;
394       struct group_statistics *gs;
395       struct group_statistics *totals = &vars[v]->p.ww.ugs; 
396
397       int count = 0 ;      
398       char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
399
400       struct hsh_table *group_hash = vars[v]->p.ww.group_hash;
401
402
403       tab_text (t, 0, row, TAB_LEFT | TAT_TITLE, s);
404       if ( v > 0) 
405         tab_hline(t, TAL_1, 0, n_cols - 1 , row);
406
407
408       for (gs =  hsh_first (group_hash,&g); 
409            gs != 0; 
410            gs = hsh_next(group_hash,&g))
411         {
412           const char *s = val_labs_find(indep_var->val_labs, gs->id );
413   
414           if ( s ) 
415             tab_text (t, 1, row + count, 
416                       TAB_LEFT | TAT_TITLE ,s);
417           else if ( indep_var->width != 0 ) 
418             tab_text (t, 1, row + count,
419                       TAB_LEFT | TAT_TITLE, gs->id.s);
420           else
421             tab_text (t, 1, row + count,
422                       TAB_LEFT | TAT_TITLE | TAT_PRINTF, "%g", gs->id.f);
423           
424
425           /* Now fill in the numbers ... */
426
427           tab_float (t, 2, row + count, 0, gs->n, 8,0);
428
429           tab_float (t, 3, row + count, 0, gs->mean,8,2);
430           
431           tab_float (t, 4, row + count, 0, gs->std_dev,8,2);
432
433           std_error = gs->std_dev/sqrt(gs->n) ;
434           tab_float (t, 5, row + count, 0, 
435                      std_error, 8,2);
436
437           /* Now the confidence interval */
438       
439           T = gsl_cdf_tdist_Qinv(q,gs->n - 1);
440
441           tab_float(t, 6, row + count, 0,
442                     gs->mean - T * std_error, 8, 2); 
443
444           tab_float(t, 7, row + count, 0,
445                     gs->mean + T * std_error, 8, 2); 
446
447           /* Min and Max */
448
449           tab_float(t, 8, row + count, 0,  gs->minimum, 8, 2); 
450           tab_float(t, 9, row + count, 0,  gs->maximum, 8, 2); 
451
452           count++ ; 
453         }
454
455       tab_text (t, 1, row + count, 
456                       TAB_LEFT | TAT_TITLE ,_("Total"));
457
458       tab_float (t, 2, row + count, 0, totals->n, 8,0);
459
460       tab_float (t, 3, row + count, 0, totals->mean, 8,2);
461
462       tab_float (t, 4, row + count, 0, totals->std_dev,8,2);
463
464       std_error = totals->std_dev/sqrt(totals->n) ;
465
466       tab_float (t, 5, row + count, 0, std_error, 8,2);
467
468       /* Now the confidence interval */
469       
470       T = gsl_cdf_tdist_Qinv(q,totals->n - 1);
471
472       tab_float(t, 6, row + count, 0,
473                 totals->mean - T * std_error, 8, 2); 
474
475       tab_float(t, 7, row + count, 0,
476                 totals->mean + T * std_error, 8, 2); 
477
478       /* Min and Max */
479
480       tab_float(t, 8, row + count, 0,  totals->minimum, 8, 2); 
481       tab_float(t, 9, row + count, 0,  totals->maximum, 8, 2); 
482
483       row += vars[v]->p.ww.n_groups + 1;
484     }
485
486
487   tab_submit (t);
488
489
490 }
491
492 /* Show the homogeneity table */
493 static void 
494 show_homogeneity(void)
495 {
496   int v;
497   int n_cols = 5;
498   int n_rows = n_vars + 1;
499
500   struct tab_table *t;
501
502
503   t = tab_create (n_cols,n_rows,0);
504   tab_headers (t, 1, 0, 1, 0);
505   tab_dim (t, tab_natural_dimensions);
506
507   /* Put a frame around the entire box, and vertical lines inside */
508   tab_box (t, 
509            TAL_2, TAL_2,
510            -1, TAL_1,
511            0, 0,
512            n_cols - 1, n_rows - 1);
513
514
515   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
516   tab_vline(t, TAL_2, 1, 0, n_rows - 1);
517
518
519   tab_text (t,  1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
520   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
521   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
522   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
523   
524
525   tab_title (t, 0, _("Test of Homogeneity of Variances"));
526
527   for ( v=0 ; v < n_vars ; ++v ) 
528     {
529       char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
530
531       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
532     }
533
534   tab_submit (t);
535
536
537 }
538
539
540 /* Show the contrast coefficients table */
541 static void 
542 show_contrast_coeffs(void)
543 {
544   char *s;
545   int n_cols = 2 + ostensible_number_of_groups;
546   int n_rows = 2 + cmd.sbc_contrast;
547   struct hsh_iterator g;
548   union value *group_value;
549   int count = 0 ;      
550
551
552   struct tab_table *t;
553
554
555   t = tab_create (n_cols,n_rows,0);
556   tab_headers (t, 2, 0, 2, 0);
557   tab_dim (t, tab_natural_dimensions);
558
559   /* Put a frame around the entire box, and vertical lines inside */
560   tab_box (t, 
561            TAL_2, TAL_2,
562            -1, TAL_1,
563            0, 0,
564            n_cols - 1, n_rows - 1);
565
566
567   tab_box (t, 
568            -1,-1,
569            TAL_0, TAL_0,
570            2, 0,
571            n_cols - 1, 0);
572
573   tab_box (t,
574            -1,-1,
575            TAL_0, TAL_0,
576            0,0,
577            1,1);
578
579
580   tab_hline(t, TAL_1, 2, n_cols - 1, 1);
581
582
583   tab_hline(t, TAL_2, 0, n_cols - 1, 2);
584   tab_vline(t, TAL_2, 2, 0, n_rows - 1);
585
586
587   tab_title (t, 0, _("Contrast Coefficients"));
588
589   tab_text (t,  0, 2, TAB_LEFT | TAT_TITLE, _("Contrast"));
590
591   s = (indep_var->label) ? indep_var->label : indep_var->name;
592
593   tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, s);
594
595   for (group_value =  hsh_first (global_group_hash,&g); 
596        group_value != 0; 
597        group_value = hsh_next(global_group_hash,&g))
598     {
599       int i;
600       char *lab;
601
602       lab = val_labs_find(indep_var->val_labs,*group_value);
603   
604       if ( lab ) 
605         tab_text (t, count + 2, 1,
606                   TAB_CENTER | TAT_TITLE ,lab);
607       else
608         tab_text (t, count + 2, 1, 
609                   TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%g", group_value->f);
610
611       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
612         {
613           tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
614           tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
615                    subc_list_double_at(&cmd.dl_contrast[i],count)
616                    );
617         }
618           
619       count++ ; 
620     }
621
622   tab_submit (t);
623
624 }
625
626
627 /* Show the results of the contrast tests */
628 static void 
629 show_contrast_tests(void)
630 {
631   int v;
632   int n_cols = 8;
633   int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast;
634
635   struct tab_table *t;
636
637   t = tab_create (n_cols,n_rows,0);
638   tab_headers (t, 3, 0, 1, 0);
639   tab_dim (t, tab_natural_dimensions);
640
641   /* Put a frame around the entire box, and vertical lines inside */
642   tab_box (t, 
643            TAL_2, TAL_2,
644            -1, TAL_1,
645            0, 0,
646            n_cols - 1, n_rows - 1);
647
648   tab_box (t, 
649            -1,-1,
650            TAL_0, TAL_0,
651            0, 0,
652            2, 0);
653
654   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
655   tab_vline(t, TAL_2, 3, 0, n_rows - 1);
656
657
658   tab_title (t, 0, _("Contrast Tests"));
659
660   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("Contrast"));
661   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast"));
662   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
663   tab_text (t,  5, 0, TAB_CENTER | TAT_TITLE, _("t"));
664   tab_text (t,  6, 0, TAB_CENTER | TAT_TITLE, _("df"));
665   tab_text (t,  7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
666
667   for ( v = 0 ; v < n_vars ; ++v ) 
668     {
669       int i;
670       int lines_per_variable = 2 * cmd.sbc_contrast;
671
672
673       tab_text (t,  0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE,
674                 vars[v]->label?vars[v]->label:vars[v]->name);
675
676
677
678       for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) 
679         {
680           int ci;
681           double contrast_value = 0.0;
682           double coef_msq = 0.0;
683           struct oneway_proc *ww = &vars[v]->p.ww ;
684           struct hsh_table *group_hash = ww->group_hash;
685           struct hsh_iterator g;
686           struct group_statistics *gs;
687
688           double T;
689           double std_error_contrast ;
690           double df;
691           double sec_vneq=0.0;
692
693
694           /* Note: The calculation of the degrees of freedom in the variances 
695              not  equal case is painfull!!
696              The following formula may help to understand it:
697              \frac{\left(\sum_{i=1}^k{c_i^2\frac{s_i^2}{n_i}}\right)^2}
698              {
699              \sum_{i=1}^k\left(
700                 \frac{\left(c_i^2\frac{s_i^2}{n_i}\right)^2}  {n_i-1}
701              \right)
702              }
703           */
704
705           double df_denominator = 0.0;
706           double df_numerator = 0.0;
707
708           
709           if ( i == 0 ) 
710             {
711               tab_text (t,  1, (v * lines_per_variable) + i + 1, 
712                         TAB_LEFT | TAT_TITLE,
713                         _("Assume equal variances"));
714
715               tab_text (t,  1, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
716                         TAB_LEFT | TAT_TITLE, 
717                         _("Does not assume equal"));
718             }
719
720           tab_text (t,  2, (v * lines_per_variable) + i + 1, 
721                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
722
723
724           tab_text (t,  2, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
725                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
726
727           /* FIXME: Potential danger here.
728              We're ASSUMING THE array is in the order corresponding to the 
729              hash order. */
730           for (ci = 0, gs = hsh_first (group_hash,&g);  
731                gs != 0;
732                ++ci, gs = hsh_next(group_hash,&g))
733             {
734
735               const double coef = subc_list_double_at(&cmd.dl_contrast[i],ci);
736               const double winv = (gs->std_dev * gs->std_dev) / gs->n;
737
738               contrast_value += coef * gs->mean;
739
740               coef_msq += (coef * coef) / gs->n ; 
741
742               sec_vneq += (coef * coef) * (gs->std_dev * gs->std_dev ) /gs->n ;
743
744               df_numerator += (coef * coef) * winv;
745               df_denominator += pow2((coef * coef) * winv) / (gs->n - 1);
746
747             }
748           sec_vneq = sqrt(sec_vneq);
749
750
751           df_numerator = pow2(df_numerator);
752           
753
754           tab_float (t,  3, (v * lines_per_variable) + i + 1, 
755                      TAB_RIGHT, contrast_value, 8,2);
756
757           tab_float (t,  3, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
758                      TAB_RIGHT, contrast_value, 8,2);
759
760
761           std_error_contrast = sqrt(vars[v]->p.ww.mse * coef_msq);
762
763           /* Std. Error */
764           tab_float (t,  4, (v * lines_per_variable) + i + 1, 
765                      TAB_RIGHT, std_error_contrast,
766                      8,3);
767
768           T = fabs(contrast_value / std_error_contrast) ;
769
770           /* T Statistic */
771
772           tab_float (t,  5, (v * lines_per_variable) + i + 1, 
773                      TAB_RIGHT, T,
774                      8,3);
775
776           df = ww->ugs.n - ww->n_groups;
777
778           /* Degrees of Freedom */
779           tab_float (t,  6, (v * lines_per_variable) + i + 1, 
780                      TAB_RIGHT,  df,
781                      8,0);
782
783
784           /* Significance TWO TAILED !!*/
785           tab_float (t,  7, (v * lines_per_variable) + i + 1, 
786                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
787                      8,3);
788
789
790           /* Now for the Variances NOT Equal case */
791
792           /* Std. Error */
793           tab_float (t,  4, 
794                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
795                      TAB_RIGHT, sec_vneq,
796                      8,3);
797
798
799           T = contrast_value / sec_vneq;
800           tab_float (t,  5, 
801                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
802                      TAB_RIGHT, T,
803                      8,3);
804
805
806           df = df_numerator / df_denominator;
807
808           tab_float (t,  6, 
809                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
810                      TAB_RIGHT, df,
811                      8,3);
812
813           /* The Significance */
814
815           tab_float (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
816                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
817                      8,3);
818
819
820         }
821
822       if ( v > 0 ) 
823         tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1);
824     }
825
826   tab_submit (t);
827
828 }
829
830
831 /* ONEWAY ANOVA Calculations */
832
833 static void  postcalc (  struct cmd_oneway *cmd UNUSED );
834
835 static void  precalc ( struct cmd_oneway *cmd UNUSED );
836
837 int  compare_group_id (const struct group_statistics *a, 
838                        const struct group_statistics *b, int width);
839
840 unsigned int hash_group_id(const struct group_statistics *v, int width);
841
842 void  free_group_id(struct group_statistics *v, void *aux UNUSED);
843
844
845
846
847 int 
848 compare_group_id (const struct group_statistics *a, 
849                   const struct group_statistics *b, int width)
850 {
851   return compare_values(&a->id, &b->id, width);
852 }
853
854 unsigned int
855 hash_group_id(const struct group_statistics *v, int width)
856 {
857   return hash_value ( &v->id, width);
858 }
859
860 void 
861 free_group_id(struct group_statistics *v, void *aux UNUSED)
862 {
863   free(v);
864 }
865
866
867 /* Pre calculations */
868 static void 
869 precalc ( struct cmd_oneway *cmd UNUSED )
870 {
871   int i=0;
872
873   for(i=0; i< n_vars ; ++i) 
874     {
875       struct group_statistics *totals = &vars[i]->p.ww.ugs;
876       
877       /* Create a hash for each of the dependent variables.
878          The hash contains a group_statistics structure, 
879          and is keyed by value of the independent variable */
880
881       vars[i]->p.ww.group_hash = 
882         hsh_create(4, 
883                    (hsh_compare_func *) compare_group_id,
884                    (hsh_hash_func *) hash_group_id,
885                    (hsh_free_func *) free_group_id,
886                    (void *) indep_var->width );
887
888
889       totals->sum=0;
890       totals->n=0;
891       totals->ssq=0;
892       totals->sum_diff=0;
893       totals->maximum = - DBL_MAX;
894       totals->minimum = DBL_MAX;
895     }
896 }
897
898
899 static void 
900 calculate(const struct casefile *cf, void *cmd_)
901 {
902   struct casereader *r;
903   struct ccase c;
904
905
906   struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
907
908   global_group_hash = hsh_create(4, 
909                                  (hsh_compare_func *) compare_values,
910                                  (hsh_hash_func *) hash_value,
911                                  0,
912                                  (void *) indep_var->width );
913
914   precalc(cmd);
915
916   for(r = casefile_get_reader (cf);
917       casereader_read (r, &c) ;
918       case_destroy (&c)) 
919     {
920       int i;
921
922       const double weight = 
923         dict_get_case_weight(default_dict,&c,&bad_weight_warn);
924       
925       const union value *indep_val = case_data (&c, indep_var->fv);
926           
927       hsh_insert ( global_group_hash, (void *) indep_val );
928
929
930       for ( i = 0 ; i < n_vars ; ++i ) 
931         {
932           const struct variable *v = vars[i];
933
934           const union value *val = case_data (&c, v->fv);
935
936           struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
937
938           struct group_statistics *gs;
939
940           gs = hsh_find(group_hash, (void *) indep_val );
941
942           if ( ! gs ) 
943             {
944               gs = (struct group_statistics *) 
945                 xmalloc (sizeof(struct group_statistics));
946
947               gs->id = *indep_val;
948               gs->sum=0;
949               gs->n=0;
950               gs->ssq=0;
951               gs->sum_diff=0;
952               gs->minimum = DBL_MAX;
953               gs->maximum = -DBL_MAX;
954
955               hsh_insert ( group_hash, (void *) gs );
956             }
957           
958           if (! value_is_missing(val,v) )
959             {
960               struct group_statistics *totals = &vars[i]->p.ww.ugs;
961
962               totals->n+=weight;
963               totals->sum+=weight * val->f;
964               totals->ssq+=weight * val->f * val->f;
965
966               if ( val->f * weight  < totals->minimum ) 
967                 totals->minimum = val->f * weight;
968
969               if ( val->f * weight  > totals->maximum ) 
970                 totals->maximum = val->f * weight;
971
972               gs->n+=weight;
973               gs->sum+=weight * val->f;
974               gs->ssq+=weight * val->f * val->f;
975
976               if ( val->f * weight  < gs->minimum ) 
977                 gs->minimum = val->f * weight;
978
979               if ( val->f * weight  > gs->maximum ) 
980                 gs->maximum = val->f * weight;
981             }
982
983           vars[i]->p.ww.n_groups = hsh_count ( group_hash );
984         }
985   
986     }
987   casereader_destroy (r);
988
989   postcalc(cmd);
990
991   ostensible_number_of_groups = hsh_count (global_group_hash);
992
993 }
994
995
996 /* Post calculations for the ONEWAY command */
997 void 
998 postcalc (  struct cmd_oneway *cmd UNUSED )
999 {
1000   int i=0;
1001
1002
1003   for(i = 0; i < n_vars ; ++i) 
1004     {
1005       struct hsh_table *group_hash = vars[i]->p.ww.group_hash;
1006       struct group_statistics *totals = &vars[i]->p.ww.ugs;
1007
1008       struct hsh_iterator g;
1009       struct group_statistics *gs;
1010
1011       for (gs =  hsh_first (group_hash,&g); 
1012            gs != 0; 
1013            gs = hsh_next(group_hash,&g))
1014         {
1015           gs->mean=gs->sum / gs->n;
1016           gs->s_std_dev= sqrt(
1017                               ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1018                               ) ;
1019
1020           gs->std_dev= sqrt(
1021                             gs->n/(gs->n-1) *
1022                             ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1023                             ) ;
1024
1025           gs->se_mean = gs->std_dev / sqrt(gs->n);
1026           gs->mean_diff= gs->sum_diff / gs->n;
1027
1028         }
1029
1030
1031
1032       totals->mean = totals->sum / totals->n;
1033       totals->std_dev= sqrt(
1034                             totals->n/(totals->n-1) *
1035                             ( (totals->ssq / totals->n ) - totals->mean * totals->mean )
1036                             ) ;
1037
1038       totals->se_mean = totals->std_dev / sqrt(totals->n);
1039         
1040
1041
1042       
1043     }
1044 }