ff6b79b66e9d322eac109ce062ac5806cf8bfef5
[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 = (vars[i]->label) ? vars[i]->label : vars[i]->name;
301
302
303       tab_text (t, 0, i * 3 + 1, TAB_LEFT | TAT_TITLE, s);
304       tab_text (t, 1, i * 3 + 1, TAB_LEFT | TAT_TITLE, _("Between Groups"));
305       tab_text (t, 1, i * 3 + 2, TAB_LEFT | TAT_TITLE, _("Within Groups"));
306       tab_text (t, 1, i * 3 + 3, TAB_LEFT | TAT_TITLE, _("Total"));
307       
308       if (i > 0)
309         tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1);
310
311       {
312         const double sst = totals->ssq - ( totals->sum * totals->sum) / totals->n ;
313         const double df1 = vars[i]->p.grp_data.n_groups - 1;
314         const double df2 = totals->n - vars[i]->p.grp_data.n_groups ;
315         const double msa = ssa / df1;
316         
317         vars[i]->p.grp_data.mse  = (sst - ssa) / df2;
318         
319         
320         /* Sums of Squares */
321         tab_float (t, 2, i * 3 + 1, 0, ssa, 10, 2);
322         tab_float (t, 2, i * 3 + 3, 0, sst, 10, 2);
323         tab_float (t, 2, i * 3 + 2, 0, sst - ssa, 10, 2);
324
325
326         /* Degrees of freedom */
327         tab_float (t, 3, i * 3 + 1, 0, df1, 4, 0);
328         tab_float (t, 3, i * 3 + 2, 0, df2, 4, 0);
329         tab_float (t, 3, i * 3 + 3, 0, totals->n - 1, 4, 0);
330
331         /* Mean Squares */
332         tab_float (t, 4, i * 3 + 1, TAB_RIGHT, msa, 8, 3);
333         tab_float (t, 4, i * 3 + 2, TAB_RIGHT, vars[i]->p.grp_data.mse, 8, 3);
334         
335
336         { 
337           const double F = msa/vars[i]->p.grp_data.mse ;
338
339           /* The F value */
340           tab_float (t, 5, i * 3 + 1, 0,  F, 8, 3);
341         
342           /* The significance */
343           tab_float (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
344         }
345
346       }
347
348     }
349
350
351   tab_title (t, 0, _("ANOVA"));
352   tab_submit (t);
353
354
355 }
356
357 /* Show the descriptives table */
358 static void  
359 show_descriptives(void)
360 {
361   int v;
362   int n_cols =10;
363   struct tab_table *t;
364   int row;
365
366   const double confidence=0.95;
367   const double q = (1.0 - confidence) / 2.0;
368
369   
370   int n_rows = 2 ; 
371
372
373
374   for ( v = 0 ; v < n_vars ; ++v ) 
375     n_rows += vars[v]->p.grp_data.n_groups + 1;
376
377   t = tab_create (n_cols,n_rows,0);
378   tab_headers (t, 2, 0, 2, 0);
379   tab_dim (t, tab_natural_dimensions);
380
381
382   /* Put a frame around the entire box, and vertical lines inside */
383   tab_box (t, 
384            TAL_2, TAL_2,
385            -1, TAL_1,
386            0, 0,
387            n_cols - 1, n_rows - 1);
388
389   /* Underline headers */
390   tab_hline (t, TAL_2, 0, n_cols - 1, 2 );
391   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
392   
393   tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("N"));
394   tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Mean"));
395   tab_text (t, 4, 1, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
396   tab_text (t, 5, 1, TAB_CENTER | TAT_TITLE, _("Std. Error"));
397
398
399   tab_vline(t, TAL_0, 7, 0, 0);
400   tab_hline(t, TAL_1, 6, 7, 1);
401   tab_joint_text (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF, _("%g%% Confidence Interval for Mean"),confidence*100.0);
402
403   tab_text (t, 6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound"));
404   tab_text (t, 7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound"));
405
406   tab_text (t, 8, 1, TAB_CENTER | TAT_TITLE, _("Minimum"));
407   tab_text (t, 9, 1, TAB_CENTER | TAT_TITLE, _("Maximum"));
408
409
410   tab_title (t, 0, _("Descriptives"));
411
412
413   row = 2;
414   for ( v=0 ; v < n_vars ; ++v ) 
415     {
416       double T;
417       double std_error;
418
419
420       struct hsh_iterator g;
421       struct group_statistics *gs;
422       struct group_statistics *totals = &vars[v]->p.grp_data.ugs; 
423
424       int count = 0 ;      
425       char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
426
427       struct hsh_table *group_hash = vars[v]->p.grp_data.group_hash;
428
429
430       tab_text (t, 0, row, TAB_LEFT | TAT_TITLE, s);
431       if ( v > 0) 
432         tab_hline(t, TAL_1, 0, n_cols - 1 , row);
433
434
435       for (gs =  hsh_first (group_hash,&g); 
436            gs != 0; 
437            gs = hsh_next(group_hash,&g))
438         {
439           const char *s = val_labs_find(indep_var->val_labs, gs->id );
440   
441           if ( s ) 
442             tab_text (t, 1, row + count, 
443                       TAB_LEFT | TAT_TITLE ,s);
444           else if ( indep_var->width != 0 ) 
445             tab_text (t, 1, row + count,
446                       TAB_LEFT | TAT_TITLE, gs->id.s);
447           else
448             tab_text (t, 1, row + count,
449                       TAB_LEFT | TAT_TITLE | TAT_PRINTF, "%g", gs->id.f);
450           
451
452           /* Now fill in the numbers ... */
453
454           tab_float (t, 2, row + count, 0, gs->n, 8,0);
455
456           tab_float (t, 3, row + count, 0, gs->mean,8,2);
457           
458           tab_float (t, 4, row + count, 0, gs->std_dev,8,2);
459
460           std_error = gs->std_dev/sqrt(gs->n) ;
461           tab_float (t, 5, row + count, 0, 
462                      std_error, 8,2);
463
464           /* Now the confidence interval */
465       
466           T = gsl_cdf_tdist_Qinv(q,gs->n - 1);
467
468           tab_float(t, 6, row + count, 0,
469                     gs->mean - T * std_error, 8, 2); 
470
471           tab_float(t, 7, row + count, 0,
472                     gs->mean + T * std_error, 8, 2); 
473
474           /* Min and Max */
475
476           tab_float(t, 8, row + count, 0,  gs->minimum, 8, 2); 
477           tab_float(t, 9, row + count, 0,  gs->maximum, 8, 2); 
478
479           count++ ; 
480         }
481
482       tab_text (t, 1, row + count, 
483                       TAB_LEFT | TAT_TITLE ,_("Total"));
484
485       tab_float (t, 2, row + count, 0, totals->n, 8,0);
486
487       tab_float (t, 3, row + count, 0, totals->mean, 8,2);
488
489       tab_float (t, 4, row + count, 0, totals->std_dev,8,2);
490
491       std_error = totals->std_dev/sqrt(totals->n) ;
492
493       tab_float (t, 5, row + count, 0, std_error, 8,2);
494
495       /* Now the confidence interval */
496       
497       T = gsl_cdf_tdist_Qinv(q,totals->n - 1);
498
499       tab_float(t, 6, row + count, 0,
500                 totals->mean - T * std_error, 8, 2); 
501
502       tab_float(t, 7, row + count, 0,
503                 totals->mean + T * std_error, 8, 2); 
504
505       /* Min and Max */
506
507       tab_float(t, 8, row + count, 0,  totals->minimum, 8, 2); 
508       tab_float(t, 9, row + count, 0,  totals->maximum, 8, 2); 
509
510       row += vars[v]->p.grp_data.n_groups + 1;
511     }
512
513
514   tab_submit (t);
515
516
517 }
518
519 /* Show the homogeneity table */
520 static void 
521 show_homogeneity(void)
522 {
523   int v;
524   int n_cols = 5;
525   int n_rows = n_vars + 1;
526
527   struct tab_table *t;
528
529
530   t = tab_create (n_cols,n_rows,0);
531   tab_headers (t, 1, 0, 1, 0);
532   tab_dim (t, tab_natural_dimensions);
533
534   /* Put a frame around the entire box, and vertical lines inside */
535   tab_box (t, 
536            TAL_2, TAL_2,
537            -1, TAL_1,
538            0, 0,
539            n_cols - 1, n_rows - 1);
540
541
542   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
543   tab_vline(t, TAL_2, 1, 0, n_rows - 1);
544
545
546   tab_text (t,  1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
547   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
548   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
549   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
550   
551
552   tab_title (t, 0, _("Test of Homogeneity of Variances"));
553
554   for ( v=0 ; v < n_vars ; ++v ) 
555     {
556       double F;
557       const struct variable *var = vars[v];
558       const char *s = (var->label) ? var->label : var->name;
559       const struct group_statistics *totals = &var->p.grp_data.ugs;
560
561       const double df1 = var->p.grp_data.n_groups - 1;
562       const double df2 = totals->n - var->p.grp_data.n_groups ;
563
564       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
565
566       F = var->p.grp_data.levene;
567       tab_float (t, 1, v + 1, TAB_RIGHT, F, 8,3);
568       tab_float (t, 2, v + 1, TAB_RIGHT, df1 ,8,0);
569       tab_float (t, 3, v + 1, TAB_RIGHT, df2 ,8,0);
570
571       /* Now the significance */
572       tab_float (t, 4, v + 1, TAB_RIGHT,gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
573     }
574
575   tab_submit (t);
576
577
578 }
579
580
581 /* Show the contrast coefficients table */
582 static void 
583 show_contrast_coeffs(short *bad_contrast)
584 {
585   char *s;
586   int n_cols = 2 + ostensible_number_of_groups;
587   int n_rows = 2 + cmd.sbc_contrast;
588   struct hsh_iterator g;
589   union value *group_value;
590   int count = 0 ;      
591
592
593   struct tab_table *t;
594
595
596   t = tab_create (n_cols,n_rows,0);
597   tab_headers (t, 2, 0, 2, 0);
598   tab_dim (t, tab_natural_dimensions);
599
600   /* Put a frame around the entire box, and vertical lines inside */
601   tab_box (t, 
602            TAL_2, TAL_2,
603            -1, TAL_1,
604            0, 0,
605            n_cols - 1, n_rows - 1);
606
607
608   tab_box (t, 
609            -1,-1,
610            TAL_0, TAL_0,
611            2, 0,
612            n_cols - 1, 0);
613
614   tab_box (t,
615            -1,-1,
616            TAL_0, TAL_0,
617            0,0,
618            1,1);
619
620
621   tab_hline(t, TAL_1, 2, n_cols - 1, 1);
622
623
624   tab_hline(t, TAL_2, 0, n_cols - 1, 2);
625   tab_vline(t, TAL_2, 2, 0, n_rows - 1);
626
627
628   tab_title (t, 0, _("Contrast Coefficients"));
629
630   tab_text (t,  0, 2, TAB_LEFT | TAT_TITLE, _("Contrast"));
631
632   s = (indep_var->label) ? indep_var->label : indep_var->name;
633
634   tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, s);
635
636   for (group_value =  hsh_first (global_group_hash,&g); 
637        group_value != 0; 
638        group_value = hsh_next(global_group_hash,&g))
639     {
640       int i;
641       char *lab;
642
643
644       lab = val_labs_find(indep_var->val_labs,*group_value);
645   
646       if ( lab ) 
647         tab_text (t, count + 2, 1,
648                   TAB_CENTER | TAT_TITLE ,lab);
649       else
650         tab_text (t, count + 2, 1, 
651                   TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%g", group_value->f);
652
653       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
654         {
655
656           tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
657
658           if ( bad_contrast[i] ) 
659             tab_text(t, count + 2, i + 2, TAB_RIGHT, "?" );
660           else
661             tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
662                      subc_list_double_at(&cmd.dl_contrast[i],count)
663                      );
664         }
665           
666       count++ ; 
667     }
668
669   tab_submit (t);
670
671 }
672
673
674 /* Show the results of the contrast tests */
675 static void 
676 show_contrast_tests(short *bad_contrast)
677 {
678   int v;
679   int n_cols = 8;
680   int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast;
681
682   struct tab_table *t;
683
684   t = tab_create (n_cols,n_rows,0);
685   tab_headers (t, 3, 0, 1, 0);
686   tab_dim (t, tab_natural_dimensions);
687
688   /* Put a frame around the entire box, and vertical lines inside */
689   tab_box (t, 
690            TAL_2, TAL_2,
691            -1, TAL_1,
692            0, 0,
693            n_cols - 1, n_rows - 1);
694
695   tab_box (t, 
696            -1,-1,
697            TAL_0, TAL_0,
698            0, 0,
699            2, 0);
700
701   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
702   tab_vline(t, TAL_2, 3, 0, n_rows - 1);
703
704
705   tab_title (t, 0, _("Contrast Tests"));
706
707   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("Contrast"));
708   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast"));
709   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
710   tab_text (t,  5, 0, TAB_CENTER | TAT_TITLE, _("t"));
711   tab_text (t,  6, 0, TAB_CENTER | TAT_TITLE, _("df"));
712   tab_text (t,  7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
713
714   for ( v = 0 ; v < n_vars ; ++v ) 
715     {
716       int i;
717       int lines_per_variable = 2 * cmd.sbc_contrast;
718
719
720       tab_text (t,  0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE,
721                 vars[v]->label?vars[v]->label:vars[v]->name);
722
723
724
725       for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) 
726         {
727           int ci;
728           double contrast_value = 0.0;
729           double coef_msq = 0.0;
730           struct group_proc *grp_data = &vars[v]->p.grp_data ;
731           struct hsh_table *group_hash = grp_data->group_hash;
732           struct hsh_iterator g;
733           struct group_statistics *gs;
734
735           double T;
736           double std_error_contrast ;
737           double df;
738           double sec_vneq=0.0;
739
740
741           /* Note: The calculation of the degrees of freedom in the variances 
742              not  equal case is painfull!!
743              The following formula may help to understand it:
744              \frac{\left(\sum_{i=1}^k{c_i^2\frac{s_i^2}{n_i}}\right)^2}
745              {
746              \sum_{i=1}^k\left(
747                 \frac{\left(c_i^2\frac{s_i^2}{n_i}\right)^2}  {n_i-1}
748              \right)
749              }
750           */
751
752           double df_denominator = 0.0;
753           double df_numerator = 0.0;
754
755           
756           if ( i == 0 ) 
757             {
758               tab_text (t,  1, (v * lines_per_variable) + i + 1, 
759                         TAB_LEFT | TAT_TITLE,
760                         _("Assume equal variances"));
761
762               tab_text (t,  1, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
763                         TAB_LEFT | TAT_TITLE, 
764                         _("Does not assume equal"));
765             }
766
767           tab_text (t,  2, (v * lines_per_variable) + i + 1, 
768                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
769
770
771           tab_text (t,  2, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
772                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
773
774
775           if ( bad_contrast[i]) 
776             continue;
777
778           /* FIXME: Potential danger here.
779              We're ASSUMING THE array is in the order corresponding to the 
780              hash order. */
781           for (ci = 0, gs = hsh_first (group_hash,&g);  
782                gs != 0;
783                ++ci, gs = hsh_next(group_hash,&g))
784             {
785
786               const double coef = subc_list_double_at(&cmd.dl_contrast[i],ci);
787               const double winv = (gs->std_dev * gs->std_dev) / gs->n;
788
789               contrast_value += coef * gs->mean;
790
791               coef_msq += (coef * coef) / gs->n ; 
792
793               sec_vneq += (coef * coef) * (gs->std_dev * gs->std_dev ) /gs->n ;
794
795               df_numerator += (coef * coef) * winv;
796               df_denominator += pow2((coef * coef) * winv) / (gs->n - 1);
797
798             }
799           sec_vneq = sqrt(sec_vneq);
800
801           df_numerator = pow2(df_numerator);
802
803           tab_float (t,  3, (v * lines_per_variable) + i + 1, 
804                      TAB_RIGHT, contrast_value, 8,2);
805
806           tab_float (t,  3, (v * lines_per_variable) + i + 1 + 
807                      cmd.sbc_contrast,
808                      TAB_RIGHT, contrast_value, 8,2);
809
810           std_error_contrast = sqrt(vars[v]->p.grp_data.mse * coef_msq);
811
812           /* Std. Error */
813           tab_float (t,  4, (v * lines_per_variable) + i + 1, 
814                      TAB_RIGHT, std_error_contrast,
815                      8,3);
816
817           T = fabs(contrast_value / std_error_contrast) ;
818
819           /* T Statistic */
820
821           tab_float (t,  5, (v * lines_per_variable) + i + 1, 
822                      TAB_RIGHT, T,
823                      8,3);
824
825           df = grp_data->ugs.n - grp_data->n_groups;
826
827           /* Degrees of Freedom */
828           tab_float (t,  6, (v * lines_per_variable) + i + 1, 
829                      TAB_RIGHT,  df,
830                      8,0);
831
832
833           /* Significance TWO TAILED !!*/
834           tab_float (t,  7, (v * lines_per_variable) + i + 1, 
835                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
836                      8,3);
837
838
839           /* Now for the Variances NOT Equal case */
840
841           /* Std. Error */
842           tab_float (t,  4, 
843                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
844                      TAB_RIGHT, sec_vneq,
845                      8,3);
846
847
848           T = contrast_value / sec_vneq;
849           tab_float (t,  5, 
850                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
851                      TAB_RIGHT, T,
852                      8,3);
853
854
855           df = df_numerator / df_denominator;
856
857           tab_float (t,  6, 
858                      (v * lines_per_variable) + i + 1 + cmd.sbc_contrast, 
859                      TAB_RIGHT, df,
860                      8,3);
861
862           /* The Significance */
863
864           tab_float (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
865                      TAB_RIGHT,  2 * gsl_cdf_tdist_Q(T,df),
866                      8,3);
867
868
869         }
870
871       if ( v > 0 ) 
872         tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1);
873     }
874
875   tab_submit (t);
876
877 }
878
879
880 /* ONEWAY ANOVA Calculations */
881
882 static void  postcalc (  struct cmd_oneway *cmd UNUSED );
883
884 static void  precalc ( struct cmd_oneway *cmd UNUSED );
885
886
887
888 /* Pre calculations */
889 static void 
890 precalc ( struct cmd_oneway *cmd UNUSED )
891 {
892   int i=0;
893
894   for(i=0; i< n_vars ; ++i) 
895     {
896       struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
897       
898       /* Create a hash for each of the dependent variables.
899          The hash contains a group_statistics structure, 
900          and is keyed by value of the independent variable */
901
902       vars[i]->p.grp_data.group_hash = 
903         hsh_create(4, 
904                    (hsh_compare_func *) compare_group,
905                    (hsh_hash_func *) hash_group,
906                    (hsh_free_func *) free_group,
907                    (void *) indep_var->width );
908
909
910       totals->sum=0;
911       totals->n=0;
912       totals->ssq=0;
913       totals->sum_diff=0;
914       totals->maximum = - DBL_MAX;
915       totals->minimum = DBL_MAX;
916     }
917 }
918
919
920 static void 
921 run_oneway(const struct casefile *cf, void *cmd_)
922 {
923   struct casereader *r;
924   struct ccase c;
925
926   struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
927
928   global_group_hash = hsh_create(4, 
929                                  (hsh_compare_func *) compare_values,
930                                  (hsh_hash_func *) hash_value,
931                                  0,
932                                  (void *) indep_var->width );
933   precalc(cmd);
934
935   for(r = casefile_get_reader (cf);
936       casereader_read (r, &c) ;
937       case_destroy (&c)) 
938     {
939       int i;
940
941       const double weight = 
942         dict_get_case_weight(default_dict,&c,&bad_weight_warn);
943       
944       const union value *indep_val = case_data (&c, indep_var->fv);
945
946       /* Deal with missing values */
947       if ( value_is_missing(indep_val,indep_var) )
948            continue;
949
950       /* Skip the entire case if /MISSING=LISTWISE is set */
951       if ( cmd->miss == ONEWAY_LISTWISE ) 
952         {
953           for(i = 0; i < n_vars ; ++i) 
954             {
955               const struct variable *v = vars[i];
956               const union value *val = case_data (&c, v->fv);
957
958               if (value_is_missing(val,v) )
959                   break;
960             }
961           if ( i != n_vars ) 
962               continue;
963
964         }
965       
966           
967       hsh_insert ( global_group_hash, (void *) indep_val );
968
969       for ( i = 0 ; i < n_vars ; ++i ) 
970         {
971           const struct variable *v = vars[i];
972
973           const union value *val = case_data (&c, v->fv);
974
975           struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash;
976
977           struct group_statistics *gs;
978
979           gs = hsh_find(group_hash, (void *) indep_val );
980
981           if ( ! gs ) 
982             {
983               gs = (struct group_statistics *) 
984                 xmalloc (sizeof(struct group_statistics));
985
986               gs->id = *indep_val;
987               gs->sum=0;
988               gs->n=0;
989               gs->ssq=0;
990               gs->sum_diff=0;
991               gs->minimum = DBL_MAX;
992               gs->maximum = -DBL_MAX;
993
994               hsh_insert ( group_hash, (void *) gs );
995             }
996           
997           if (! value_is_missing(val,v) )
998             {
999               struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
1000
1001               totals->n+=weight;
1002               totals->sum+=weight * val->f;
1003               totals->ssq+=weight * val->f * val->f;
1004
1005               if ( val->f * weight  < totals->minimum ) 
1006                 totals->minimum = val->f * weight;
1007
1008               if ( val->f * weight  > totals->maximum ) 
1009                 totals->maximum = val->f * weight;
1010
1011               gs->n+=weight;
1012               gs->sum+=weight * val->f;
1013               gs->ssq+=weight * val->f * val->f;
1014
1015               if ( val->f * weight  < gs->minimum ) 
1016                 gs->minimum = val->f * weight;
1017
1018               if ( val->f * weight  > gs->maximum ) 
1019                 gs->maximum = val->f * weight;
1020             }
1021
1022           vars[i]->p.grp_data.n_groups = hsh_count ( group_hash );
1023         }
1024   
1025     }
1026   casereader_destroy (r);
1027
1028   postcalc(cmd);
1029
1030   
1031   if ( stat_tables & STAT_HOMO ) 
1032     levene(cf, indep_var, n_vars, vars, 
1033            (cmd->miss == ONEWAY_LISTWISE) ? LEV_LISTWISE : LEV_ANALYSIS ,
1034            value_is_missing);
1035
1036   ostensible_number_of_groups = hsh_count (global_group_hash);
1037
1038
1039   output_oneway();
1040
1041
1042 }
1043
1044
1045 /* Post calculations for the ONEWAY command */
1046 void 
1047 postcalc (  struct cmd_oneway *cmd UNUSED )
1048 {
1049   int i=0;
1050
1051
1052   for(i = 0; i < n_vars ; ++i) 
1053     {
1054       struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash;
1055       struct group_statistics *totals = &vars[i]->p.grp_data.ugs;
1056
1057       struct hsh_iterator g;
1058       struct group_statistics *gs;
1059
1060       for (gs =  hsh_first (group_hash,&g); 
1061            gs != 0; 
1062            gs = hsh_next(group_hash,&g))
1063         {
1064           gs->mean=gs->sum / gs->n;
1065           gs->s_std_dev= sqrt(
1066                               ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1067                               ) ;
1068
1069           gs->std_dev= sqrt(
1070                             gs->n/(gs->n-1) *
1071                             ( (gs->ssq / gs->n ) - gs->mean * gs->mean )
1072                             ) ;
1073
1074           gs->se_mean = gs->std_dev / sqrt(gs->n);
1075           gs->mean_diff= gs->sum_diff / gs->n;
1076
1077         }
1078
1079
1080
1081       totals->mean = totals->sum / totals->n;
1082       totals->std_dev= sqrt(
1083                             totals->n/(totals->n-1) *
1084                             ( (totals->ssq / totals->n ) - totals->mean * totals->mean )
1085                             ) ;
1086
1087       totals->se_mean = totals->std_dev / sqrt(totals->n);
1088         
1089     }
1090 }