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