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