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