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