Fixed the t-test model to be consistent with the anova model.
[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 "group_proc.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.grp_data.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.grp_data.ugs;
258       struct hsh_table *group_hash = vars[i]->p.grp_data.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.grp_data.n_groups - 1;
287         const double df2 = totals->n - vars[i]->p.grp_data.n_groups ;
288         const double msa = ssa / df1;
289         
290         vars[i]->p.grp_data.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.grp_data.mse, 8, 3);
307         
308
309         { 
310           const double F = msa/vars[i]->p.grp_data.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.grp_data.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.grp_data.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.grp_data.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.grp_data.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       struct group_statistics *totals = &vars[v]->p.grp_data.ugs;
531
532       const double df1 = vars[v]->p.grp_data.n_groups - 1;
533       const double df2 = totals->n - vars[v]->p.grp_data.n_groups ;
534
535
536       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
537
538
539
540       tab_float (t, 2, v + 1, TAB_RIGHT, df1 ,8,0);
541       tab_float (t, 3, v + 1, TAB_RIGHT, df2 ,8,0);
542     }
543
544   tab_submit (t);
545
546
547 }
548
549
550 /* Show the contrast coefficients table */
551 static void 
552 show_contrast_coeffs(void)
553 {
554   char *s;
555   int n_cols = 2 + ostensible_number_of_groups;
556   int n_rows = 2 + cmd.sbc_contrast;
557   struct hsh_iterator g;
558   union value *group_value;
559   int count = 0 ;      
560
561
562   struct tab_table *t;
563
564
565   t = tab_create (n_cols,n_rows,0);
566   tab_headers (t, 2, 0, 2, 0);
567   tab_dim (t, tab_natural_dimensions);
568
569   /* Put a frame around the entire box, and vertical lines inside */
570   tab_box (t, 
571            TAL_2, TAL_2,
572            -1, TAL_1,
573            0, 0,
574            n_cols - 1, n_rows - 1);
575
576
577   tab_box (t, 
578            -1,-1,
579            TAL_0, TAL_0,
580            2, 0,
581            n_cols - 1, 0);
582
583   tab_box (t,
584            -1,-1,
585            TAL_0, TAL_0,
586            0,0,
587            1,1);
588
589
590   tab_hline(t, TAL_1, 2, n_cols - 1, 1);
591
592
593   tab_hline(t, TAL_2, 0, n_cols - 1, 2);
594   tab_vline(t, TAL_2, 2, 0, n_rows - 1);
595
596
597   tab_title (t, 0, _("Contrast Coefficients"));
598
599   tab_text (t,  0, 2, TAB_LEFT | TAT_TITLE, _("Contrast"));
600
601   s = (indep_var->label) ? indep_var->label : indep_var->name;
602
603   tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, s);
604
605   for (group_value =  hsh_first (global_group_hash,&g); 
606        group_value != 0; 
607        group_value = hsh_next(global_group_hash,&g))
608     {
609       int i;
610       char *lab;
611
612       lab = val_labs_find(indep_var->val_labs,*group_value);
613   
614       if ( lab ) 
615         tab_text (t, count + 2, 1,
616                   TAB_CENTER | TAT_TITLE ,lab);
617       else
618         tab_text (t, count + 2, 1, 
619                   TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%g", group_value->f);
620
621       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
622         {
623           tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
624           tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
625                    subc_list_double_at(&cmd.dl_contrast[i],count)
626                    );
627         }
628           
629       count++ ; 
630     }
631
632   tab_submit (t);
633
634 }
635
636
637 /* Show the results of the contrast tests */
638 static void 
639 show_contrast_tests(void)
640 {
641   int v;
642   int n_cols = 8;
643   int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast;
644
645   struct tab_table *t;
646
647   t = tab_create (n_cols,n_rows,0);
648   tab_headers (t, 3, 0, 1, 0);
649   tab_dim (t, tab_natural_dimensions);
650
651   /* Put a frame around the entire box, and vertical lines inside */
652   tab_box (t, 
653            TAL_2, TAL_2,
654            -1, TAL_1,
655            0, 0,
656            n_cols - 1, n_rows - 1);
657
658   tab_box (t, 
659            -1,-1,
660            TAL_0, TAL_0,
661            0, 0,
662            2, 0);
663
664   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
665   tab_vline(t, TAL_2, 3, 0, n_rows - 1);
666
667
668   tab_title (t, 0, _("Contrast Tests"));
669
670   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("Contrast"));
671   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast"));
672   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
673   tab_text (t,  5, 0, TAB_CENTER | TAT_TITLE, _("t"));
674   tab_text (t,  6, 0, TAB_CENTER | TAT_TITLE, _("df"));
675   tab_text (t,  7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
676
677   for ( v = 0 ; v < n_vars ; ++v ) 
678     {
679       int i;
680       int lines_per_variable = 2 * cmd.sbc_contrast;
681
682
683       tab_text (t,  0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE,
684                 vars[v]->label?vars[v]->label:vars[v]->name);
685
686
687
688       for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) 
689         {
690           int ci;
691           double contrast_value = 0.0;
692           double coef_msq = 0.0;
693           struct group_proc *grp_data = &vars[v]->p.grp_data ;
694           struct hsh_table *group_hash = grp_data->group_hash;
695           struct hsh_iterator g;
696           struct group_statistics *gs;
697
698           double T;
699           double std_error_contrast ;
700           double df;
701           double sec_vneq=0.0;
702
703
704           /* Note: The calculation of the degrees of freedom in the variances 
705              not  equal case is painfull!!
706              The following formula may help to understand it:
707              \frac{\left(\sum_{i=1}^k{c_i^2\frac{s_i^2}{n_i}}\right)^2}
708              {
709              \sum_{i=1}^k\left(
710                 \frac{\left(c_i^2\frac{s_i^2}{n_i}\right)^2}  {n_i-1}
711              \right)
712              }
713           */
714
715           double df_denominator = 0.0;
716           double df_numerator = 0.0;
717
718           
719           if ( i == 0 ) 
720             {
721               tab_text (t,  1, (v * lines_per_variable) + i + 1, 
722                         TAB_LEFT | TAT_TITLE,
723                         _("Assume equal variances"));
724
725               tab_text (t,  1, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
726                         TAB_LEFT | TAT_TITLE, 
727                         _("Does not assume equal"));
728             }
729
730           tab_text (t,  2, (v * lines_per_variable) + i + 1, 
731                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
732
733
734           tab_text (t,  2, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
735                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
736
737           /* FIXME: Potential danger here.
738              We're ASSUMING THE array is in the order corresponding to the 
739              hash order. */
740           for (ci = 0, gs = hsh_first (group_hash,&g);  
741                gs != 0;
742                ++ci, gs = hsh_next(group_hash,&g))
743             {
744
745               const double coef = subc_list_double_at(&cmd.dl_contrast[i],ci);
746               const double winv = (gs->std_dev * gs->std_dev) / gs->n;
747
748               contrast_value += coef * gs->mean;
749
750               coef_msq += (coef * coef) / gs->n ; 
751
752               sec_vneq += (coef * coef) * (gs->std_dev * gs->std_dev ) /gs->n ;
753
754               df_numerator += (coef * coef) * winv;
755               df_denominator += pow2((coef * coef) * winv) / (gs->n - 1);
756
757             }
758           sec_vneq = sqrt(sec_vneq);
759
760
761           df_numerator = pow2(df_numerator);
762           
763
764           tab_float (t,  3, (v * lines_per_variable) + i + 1, 
765                      TAB_RIGHT, contrast_value, 8,2);
766
767           tab_float (t,  3, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
768                      TAB_RIGHT, contrast_value, 8,2);
769
770
771           std_error_contrast = sqrt(vars[v]->p.grp_data.mse * coef_msq);
772
773           /* Std. Error */
774           tab_float (t,  4, (v * lines_per_variable) + i + 1, 
775                      TAB_RIGHT, std_error_contrast,
776                      8,3);
777
778           T = fabs(contrast_value / std_error_contrast) ;
779
780           /* T Statistic */
781
782           tab_float (t,  5, (v * lines_per_variable) + i + 1, 
783                      TAB_RIGHT, T,
784                      8,3);
785
786           df = grp_data->ugs.n - grp_data->n_groups;
787
788           /* Degrees of Freedom */
789           tab_float (t,  6, (v * lines_per_variable) + i + 1, 
790                      TAB_RIGHT,  df,
791                      8,0);
792
793
794           /* Significance TWO TAILED !!*/
795           tab_float (t,  7, (v * lines_per_variable) + i + 1, 
796                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
797                      8,3);
798
799
800           /* Now for the Variances NOT Equal case */
801
802           /* Std. Error */
803           tab_float (t,  4, 
804                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
805                      TAB_RIGHT, sec_vneq,
806                      8,3);
807
808
809           T = contrast_value / sec_vneq;
810           tab_float (t,  5, 
811                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
812                      TAB_RIGHT, T,
813                      8,3);
814
815
816           df = df_numerator / df_denominator;
817
818           tab_float (t,  6, 
819                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
820                      TAB_RIGHT, df,
821                      8,3);
822
823           /* The Significance */
824
825           tab_float (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
826                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
827                      8,3);
828
829
830         }
831
832       if ( v > 0 ) 
833         tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1);
834     }
835
836   tab_submit (t);
837
838 }
839
840
841 /* ONEWAY ANOVA Calculations */
842
843 static void  postcalc (  struct cmd_oneway *cmd UNUSED );
844
845 static void  precalc ( struct cmd_oneway *cmd UNUSED );
846
847
848
849 /* Pre calculations */
850 static void 
851 precalc ( struct cmd_oneway *cmd UNUSED )
852 {
853   int i=0;
854
855   for(i=0; i< n_vars ; ++i) 
856     {
857       struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
858       
859       /* Create a hash for each of the dependent variables.
860          The hash contains a group_statistics structure, 
861          and is keyed by value of the independent variable */
862
863       vars[i]->p.grp_data.group_hash = 
864         hsh_create(4, 
865                    (hsh_compare_func *) compare_group,
866                    (hsh_hash_func *) hash_group,
867                    (hsh_free_func *) free_group,
868                    (void *) indep_var->width );
869
870
871       totals->sum=0;
872       totals->n=0;
873       totals->ssq=0;
874       totals->sum_diff=0;
875       totals->maximum = - DBL_MAX;
876       totals->minimum = DBL_MAX;
877     }
878 }
879
880
881 static void 
882 calculate(const struct casefile *cf, void *cmd_)
883 {
884   struct casereader *r;
885   struct ccase c;
886
887
888   struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
889
890   global_group_hash = hsh_create(4, 
891                                  (hsh_compare_func *) compare_values,
892                                  (hsh_hash_func *) hash_value,
893                                  0,
894                                  (void *) indep_var->width );
895
896   precalc(cmd);
897
898
899
900   for(r = casefile_get_reader (cf);
901       casereader_read (r, &c) ;
902       case_destroy (&c)) 
903     {
904       int i;
905
906       const double weight = 
907         dict_get_case_weight(default_dict,&c,&bad_weight_warn);
908       
909       const union value *indep_val = case_data (&c, indep_var->fv);
910           
911       hsh_insert ( global_group_hash, (void *) indep_val );
912
913
914       for ( i = 0 ; i < n_vars ; ++i ) 
915         {
916           const struct variable *v = vars[i];
917
918           const union value *val = case_data (&c, v->fv);
919
920           struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash;
921
922           struct group_statistics *gs;
923
924           gs = hsh_find(group_hash, (void *) indep_val );
925
926           if ( ! gs ) 
927             {
928               gs = (struct group_statistics *) 
929                 xmalloc (sizeof(struct group_statistics));
930
931               gs->id = *indep_val;
932               gs->sum=0;
933               gs->n=0;
934               gs->ssq=0;
935               gs->sum_diff=0;
936               gs->minimum = DBL_MAX;
937               gs->maximum = -DBL_MAX;
938
939               hsh_insert ( group_hash, (void *) gs );
940             }
941           
942           if (! value_is_missing(val,v) )
943             {
944               struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
945
946               totals->n+=weight;
947               totals->sum+=weight * val->f;
948               totals->ssq+=weight * val->f * val->f;
949
950               if ( val->f * weight  < totals->minimum ) 
951                 totals->minimum = val->f * weight;
952
953               if ( val->f * weight  > totals->maximum ) 
954                 totals->maximum = val->f * weight;
955
956               gs->n+=weight;
957               gs->sum+=weight * val->f;
958               gs->ssq+=weight * val->f * val->f;
959
960               if ( val->f * weight  < gs->minimum ) 
961                 gs->minimum = val->f * weight;
962
963               if ( val->f * weight  > gs->maximum ) 
964                 gs->maximum = val->f * weight;
965             }
966
967           vars[i]->p.grp_data.n_groups = hsh_count ( group_hash );
968         }
969   
970     }
971   casereader_destroy (r);
972
973   postcalc(cmd);
974
975   /* 
976   levene(cf, indep_var, n_vars, vars, LEV_LISTWISE, value_is_missing);
977   */
978
979   ostensible_number_of_groups = hsh_count (global_group_hash);
980
981 }
982
983
984 /* Post calculations for the ONEWAY command */
985 void 
986 postcalc (  struct cmd_oneway *cmd UNUSED )
987 {
988   int i=0;
989
990
991   for(i = 0; i < n_vars ; ++i) 
992     {
993       struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash;
994       struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
995
996       struct hsh_iterator g;
997       struct group_statistics *gs;
998
999       for (gs =  hsh_first (group_hash,&g); 
1000            gs != 0; 
1001            gs = hsh_next(group_hash,&g))
1002         {
1003           gs->mean=gs->sum / gs->n;
1004           gs->s_std_dev= sqrt(
1005                               ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1006                               ) ;
1007
1008           gs->std_dev= sqrt(
1009                             gs->n/(gs->n-1) *
1010                             ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1011                             ) ;
1012
1013           gs->se_mean = gs->std_dev / sqrt(gs->n);
1014           gs->mean_diff= gs->sum_diff / gs->n;
1015
1016         }
1017
1018
1019
1020       totals->mean = totals->sum / totals->n;
1021       totals->std_dev= sqrt(
1022                             totals->n/(totals->n-1) *
1023                             ( (totals->ssq / totals->n ) - totals->mean * totals->mean )
1024                             ) ;
1025
1026       totals->se_mean = totals->std_dev / sqrt(totals->n);
1027         
1028
1029
1030       
1031     }
1032 }