Added framework for the ONEWAY command.
[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 "levene.h"
43
44 /* (specification)
45    "ONEWAY" (oneway_):
46      *variables=custom;
47      +missing=miss:!analysis/listwise,
48              incl:include/!exclude;
49      contrast= double list;
50      statistics[st_]=descriptives,homogeneity.
51 */
52 /* (declarations) */
53 /* (functions) */
54
55
56
57 static struct cmd_oneway cmd;
58
59 /* The independent variable */
60 static struct variable *indep_var;
61
62 /* A hash of the values of the independent variable */
63 struct hsh_table *ind_vals;
64
65 /* Number of factors (groups) */
66 static int n_groups;
67
68 /* Number of dependent variables */
69 static int n_vars;
70
71 /* The dependent variables */
72 static struct variable **vars;
73
74
75
76
77
78 /* Function to use for testing for missing values */
79 static is_missing_func value_is_missing;
80
81
82 static void calculate(const struct casefile *cf, void *_mode);
83
84
85 /* Routines to show the output tables */
86 static void show_anova_table(void);
87 static void show_descriptives(void);
88 static void show_homogeneity(void);
89 static void show_contrast_coeffs(void);
90 static void show_contrast_tests(void);
91
92
93
94 int
95 cmd_oneway(void)
96 {
97   int i;
98
99   if ( !parse_oneway(&cmd) )
100     return CMD_FAILURE;
101
102   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
103   if (cmd.incl == ONEWAY_INCLUDE ) 
104     value_is_missing = is_system_missing;
105   else
106     value_is_missing = is_missing;
107
108   multipass_procedure_with_splits (calculate, &cmd);
109
110   /* Check the sanity of the given contrast values */
111   for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
112     {
113       int j;
114       double sum = 0;
115
116       if ( subc_list_double_count(&cmd.dl_contrast[i]) != n_groups )
117         {
118           msg(SE, _("Number of contrast coefficients must equal the number of groups"));
119           return CMD_FAILURE;
120         }
121
122       for (j=0; j < n_groups ; ++j )
123         sum += subc_list_double_at(&cmd.dl_contrast[i],j);
124
125       if ( sum != 0.0 ) 
126         msg(SW,_("Coefficients for contrast %d do not total zero"),i + 1);
127     }
128
129
130   /* Show the statistics tables */
131   if ( cmd.sbc_statistics ) 
132     {
133     for (i = 0 ; i < ONEWAY_ST_count ; ++i ) 
134       {
135         if  ( ! cmd.a_statistics[i]  ) continue;
136
137         switch (i) {
138         case ONEWAY_ST_DESCRIPTIVES:
139           show_descriptives();
140           break;
141         case ONEWAY_ST_HOMOGENEITY:
142           show_homogeneity();
143           break;
144         }
145       
146       }
147   }
148
149   show_anova_table();
150      
151   if (cmd.sbc_contrast)
152     {
153       show_contrast_coeffs();
154       show_contrast_tests();
155     }
156
157   hsh_destroy(ind_vals);
158
159   return CMD_SUCCESS;
160 }
161
162
163
164
165
166 /* Parser for the variables sub command */
167 static int
168 oneway_custom_variables(struct cmd_oneway *cmd UNUSED)
169 {
170
171   lex_match('=');
172
173   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
174       && token != T_ALL)
175     return 2;
176   
177
178   if (!parse_variables (default_dict, &vars, &n_vars,
179                         PV_DUPLICATE 
180                         | PV_NUMERIC | PV_NO_SCRATCH) )
181     {
182       free (vars);
183       return 0;
184     }
185
186   assert(n_vars);
187
188   if ( ! lex_match(T_BY))
189     return 2;
190
191
192   indep_var = parse_variable();
193
194   if ( !indep_var ) 
195     {
196       msg(SE,_("`%s' is not a variable name"),tokid);
197       return 0;
198     }
199
200
201   return 1;
202 }
203
204
205 /* Show the ANOVA table */
206 static void  
207 show_anova_table(void)
208 {
209   int i;
210   int n_cols =7;
211   int n_rows = n_vars * 3 + 1;
212
213   struct tab_table *t;
214
215
216   t = tab_create (n_cols,n_rows,0);
217   tab_headers (t, 2, 0, 1, 0);
218   tab_dim (t, tab_natural_dimensions);
219
220
221   tab_box (t, 
222            TAL_2, TAL_2,
223            -1, TAL_1,
224            0, 0,
225            n_cols - 1, n_rows - 1);
226
227   tab_hline (t, TAL_2, 0, n_cols - 1, 1 );
228   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
229   tab_vline (t, TAL_0, 1, 0, 0);
230   
231   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares"));
232   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
233   tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
234   tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
235   tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
236
237
238   for ( i=0 ; i < n_vars ; ++i ) 
239     {
240       char *s = (vars[i]->label) ? vars[i]->label : vars[i]->name;
241
242       tab_text (t, 0, i * 3 + 1, TAB_LEFT | TAT_TITLE, s);
243       tab_text (t, 1, i * 3 + 1, TAB_LEFT | TAT_TITLE, _("Between Groups"));
244       tab_text (t, 1, i * 3 + 2, TAB_LEFT | TAT_TITLE, _("Within Groups"));
245       tab_text (t, 1, i * 3 + 3, TAB_LEFT | TAT_TITLE, _("Total"));
246       
247       if (i > 0)
248         tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1);
249     }
250
251
252   tab_title (t, 0, "ANOVA");
253   tab_submit (t);
254
255
256 }
257
258
259 static void 
260 calculate(const struct casefile *cf, void *cmd_)
261 {
262   struct casereader *r;
263   struct ccase c;
264
265   struct cmd_t_test *cmd = (struct cmd_t_test *) cmd_;
266
267
268   ind_vals = hsh_create(4, (hsh_compare_func *) compare_values, 
269                            (hsh_hash_func *) hash_value, 
270                            0, (void *) indep_var->width );
271
272   for(r = casefile_get_reader (cf);
273       casereader_read (r, &c) ;
274       case_destroy (&c)) 
275     {
276
277           const union value *val = case_data (&c, indep_var->fv);
278           
279           hsh_insert(ind_vals, (void *) val);
280
281           /* 
282           if (! value_is_missing(val,v) )
283             {
284               gs->n+=weight;
285               gs->sum+=weight * val->f;
286               gs->ssq+=weight * val->f * val->f;
287             }
288           */
289   
290     }
291   casereader_destroy (r);
292
293
294   n_groups = hsh_count(ind_vals);
295
296
297 }
298
299
300 /* Show the descriptives table */
301 static void  
302 show_descriptives(void)
303 {
304   int v;
305   int n_cols =10;
306   int n_rows = n_vars * (n_groups + 1 )+ 2;
307
308   struct tab_table *t;
309
310
311   t = tab_create (n_cols,n_rows,0);
312   tab_headers (t, 2, 0, 2, 0);
313   tab_dim (t, tab_natural_dimensions);
314
315
316   /* Put a frame around the entire box, and vertical lines inside */
317   tab_box (t, 
318            TAL_2, TAL_2,
319            -1, TAL_1,
320            0, 0,
321            n_cols - 1, n_rows - 1);
322
323   /* Underline headers */
324   tab_hline (t, TAL_2, 0, n_cols - 1, 2 );
325   tab_vline (t, TAL_2, 2, 0, n_rows - 1);
326   
327   tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("N"));
328   tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Mean"));
329   tab_text (t, 4, 1, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
330   tab_text (t, 5, 1, TAB_CENTER | TAT_TITLE, _("Std. Error"));
331
332
333   tab_vline(t, TAL_0, 7, 0, 0);
334   tab_hline(t, TAL_1, 6, 7, 1);
335   tab_joint_text (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE, _("95% Confidence Interval for Mean"));
336
337   tab_text (t, 6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound"));
338   tab_text (t, 7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound"));
339
340   tab_text (t, 8, 1, TAB_CENTER | TAT_TITLE, _("Minimum"));
341   tab_text (t, 9, 1, TAB_CENTER | TAT_TITLE, _("Maximum"));
342
343
344   tab_title (t, 0, "Descriptives");
345
346
347   for ( v=0 ; v < n_vars ; ++v ) 
348     {
349       struct hsh_iterator g;
350       union value *group_value;
351       int count = 0 ;      
352       char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
353
354       tab_text (t, 0, v * ( n_groups + 1 ) + 2, TAB_LEFT | TAT_TITLE, s);
355       if ( v > 0) 
356         tab_hline(t, TAL_1, 0, n_cols - 1 , v * (n_groups + 1) + 2);
357
358
359       for (group_value =  hsh_first (ind_vals,&g); 
360            group_value != 0; 
361            group_value = hsh_next(ind_vals,&g))
362         {
363           char *lab;
364
365           lab = val_labs_find(indep_var->val_labs,*group_value);
366   
367           if ( lab ) 
368             tab_text (t, 1, v * (n_groups + 1)+ count + 2, 
369                       TAB_LEFT | TAT_TITLE ,lab);
370           else
371             tab_text (t, 1, v * (n_groups + 1) + count + 2, 
372                       TAB_LEFT | TAT_TITLE | TAT_PRINTF, "%g", group_value->f);
373           
374           count++ ; 
375         }
376
377       tab_text (t, 1, v * (n_groups + 1)+ count + 2, 
378                       TAB_LEFT | TAT_TITLE ,_("Total"));
379       
380
381     }
382
383
384   tab_submit (t);
385
386
387 }
388
389
390 /* Show the homogeneity table */
391 static void 
392 show_homogeneity(void)
393 {
394   int v;
395   int n_cols = 5;
396   int n_rows = n_vars + 1;
397
398   struct tab_table *t;
399
400
401   t = tab_create (n_cols,n_rows,0);
402   tab_headers (t, 1, 0, 1, 0);
403   tab_dim (t, tab_natural_dimensions);
404
405   /* Put a frame around the entire box, and vertical lines inside */
406   tab_box (t, 
407            TAL_2, TAL_2,
408            -1, TAL_1,
409            0, 0,
410            n_cols - 1, n_rows - 1);
411
412
413   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
414   tab_vline(t, TAL_2, 1, 0, n_rows - 1);
415
416
417   tab_text (t,  1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
418   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
419   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
420   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
421   
422
423   tab_title (t, 0, _("Test of Homogeneity of Variances"));
424
425   for ( v=0 ; v < n_vars ; ++v ) 
426     {
427       char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
428
429       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
430     }
431
432   tab_submit (t);
433
434
435 }
436
437
438 /* Show the contrast coefficients table */
439 static void 
440 show_contrast_coeffs(void)
441 {
442   char *s;
443   int n_cols = 2 + n_groups;
444   int n_rows = 2 + cmd.sbc_contrast;
445   struct hsh_iterator g;
446   union value *group_value;
447   int count = 0 ;      
448
449
450   struct tab_table *t;
451
452
453   t = tab_create (n_cols,n_rows,0);
454   tab_headers (t, 2, 0, 2, 0);
455   tab_dim (t, tab_natural_dimensions);
456
457   /* Put a frame around the entire box, and vertical lines inside */
458   tab_box (t, 
459            TAL_2, TAL_2,
460            -1, TAL_1,
461            0, 0,
462            n_cols - 1, n_rows - 1);
463
464
465   tab_box (t, 
466            -1,-1,
467            TAL_0, TAL_0,
468            2, 0,
469            n_cols - 1, 0);
470
471   tab_box (t,
472            -1,-1,
473            TAL_0, TAL_0,
474            0,0,
475            1,1);
476
477
478   tab_hline(t, TAL_1, 2, n_cols - 1, 1);
479
480
481   tab_hline(t, TAL_2, 0, n_cols - 1, 2);
482   tab_vline(t, TAL_2, 2, 0, n_rows - 1);
483
484
485   tab_title (t, 0, _("Contrast Coefficients"));
486
487   tab_text (t,  0, 2, TAB_LEFT | TAT_TITLE, _("Contrast"));
488
489   s = (indep_var->label) ? indep_var->label : indep_var->name;
490
491   tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, s);
492
493   for (group_value =  hsh_first (ind_vals,&g); 
494        group_value != 0; 
495        group_value = hsh_next(ind_vals,&g))
496     {
497       int i;
498       char *lab;
499
500       lab = val_labs_find(indep_var->val_labs,*group_value);
501   
502       if ( lab ) 
503         tab_text (t, count + 2, 1,
504                   TAB_CENTER | TAT_TITLE ,lab);
505       else
506         tab_text (t, count + 2, 1, 
507                   TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%g", group_value->f);
508
509       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
510         {
511           tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
512           tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
513                    subc_list_double_at(&cmd.dl_contrast[i],count)
514                    );
515         }
516           
517       count++ ; 
518     }
519
520   tab_submit (t);
521
522 }
523
524
525
526 /* Show the results of the contrast tests */
527 static void 
528 show_contrast_tests(void)
529 {
530   int v;
531   int n_cols = 8;
532   int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast;
533
534   struct tab_table *t;
535
536   t = tab_create (n_cols,n_rows,0);
537   tab_headers (t, 3, 0, 1, 0);
538   tab_dim (t, tab_natural_dimensions);
539
540   /* Put a frame around the entire box, and vertical lines inside */
541   tab_box (t, 
542            TAL_2, TAL_2,
543            -1, TAL_1,
544            0, 0,
545            n_cols - 1, n_rows - 1);
546
547
548   tab_box (t, 
549            -1,-1,
550            TAL_0, TAL_0,
551            0, 0,
552            2, 0);
553
554   tab_hline(t, TAL_2, 0, n_cols - 1, 1);
555   tab_vline(t, TAL_2, 3, 0, n_rows - 1);
556
557
558   tab_title (t, 0, _("Contrast Tests"));
559
560   tab_text (t,  2, 0, TAB_CENTER | TAT_TITLE, _("Contrast"));
561   tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast"));
562   tab_text (t,  4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
563   tab_text (t,  5, 0, TAB_CENTER | TAT_TITLE, _("t"));
564   tab_text (t,  6, 0, TAB_CENTER | TAT_TITLE, _("df"));
565   tab_text (t,  7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
566
567   for ( v = 0 ; v < n_vars ; ++v ) 
568     {
569       int i;
570       int lines_per_variable = 2 * cmd.sbc_contrast;
571
572       tab_text (t,  0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE,
573                 vars[v]->label?vars[v]->label:vars[v]->name);
574
575       for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) 
576         {
577           tab_text (t,  1, (v * lines_per_variable) + i*2 + 1, 
578                     TAB_LEFT | TAT_TITLE, 
579                     _("Assume equal variances"));
580
581           tab_text (t,  1, (v * lines_per_variable) + i*2 + 2, 
582                     TAB_LEFT | TAT_TITLE, 
583                     _("Does not assume equal"));
584
585
586           tab_text (t,  2, (v * lines_per_variable) + i*2 + 1, 
587                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
588
589           tab_text (t,  2, (v * lines_per_variable) + i*2 + 2, 
590                     TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
591
592         }
593
594       if ( v > 0 ) 
595         tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1);
596     }
597
598   tab_submit (t);
599
600 }