Added calculations for the correlation for paired samples in t-test
[pspp-builds.git] / src / t-test.q
1 /* PSPP - computes sample statistics. -*-c-*-
2
3    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4    Written by John Williams <johnr.williams@stonebow.otago.ac.nz>.
5    Almost completly re-written by John Darrington 2004
6
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA. */
21
22 #include <config.h>
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include "alloc.h"
28 #include "str.h"
29 #include "dcdflib/cdflib.h"
30 #include "command.h"
31 #include "lexer.h"
32 #include "error.h"
33 #include "magic.h"
34 #include "tab.h"
35 #include "som.h"
36 #include "value-labels.h"
37 #include "var.h"
38 #include "vfm.h"
39 #include "pool.h"
40 #include "hash.h"
41 #include "stats.h"
42
43 /* (specification)
44    "T-TEST" (tts_):
45      groups=custom;
46      testval=double;
47      variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
48      pairs=custom;
49      +missing=miss:!analysis/listwise,
50              incl:include/!exclude;
51      format=fmt:!labels/nolabels;
52      criteria=:cin(d:criteria,"%s > 0. && %s < 1.").
53 */
54 /* (declarations) */
55 /* (functions) */
56
57 static struct cmd_t_test cmd;
58
59
60
61 static struct pool *t_test_pool ;
62
63 /* Variable for the GROUPS subcommand, if given. */
64 static struct variable *groups;
65
66 /* GROUPS: Number of values specified by the user; the values
67    specified if any. */
68 static int n_groups_values;
69 static union value groups_values[2];
70
71 /* PAIRS: Number of pairs to be compared ; each pair. */
72 static int n_pairs ;
73 struct pair 
74 {
75   struct variable *v[2];
76   double correlation;
77 };
78 static struct pair *pairs;
79
80
81 static int parse_value (union value * v, int type) ;
82
83
84 /* Structures and Functions for the Statistics Summary Box */
85 struct ssbox;
86 typedef void populate_ssbox_func(struct ssbox *ssb,
87                                             struct cmd_t_test *cmd);
88 typedef void finalize_ssbox_func(struct ssbox *ssb);
89
90 struct ssbox
91 {
92   struct tab_table *t;
93
94   populate_ssbox_func *populate;
95   finalize_ssbox_func *finalize;
96
97 };
98
99 /* Create a ssbox */
100 void ssbox_create(struct ssbox *ssb,   struct cmd_t_test *cmd, int mode);
101
102 /* Populate a ssbox according to cmd */
103 void ssbox_populate(struct ssbox *ssb, struct cmd_t_test *cmd);
104
105 /* Submit and destroy a ssbox */
106 void ssbox_finalize(struct ssbox *ssb);
107
108 /* A function to create, populate and submit the Paired Samples Correlation 
109    box */
110 void pscbox(struct cmd_t_test *cmd);
111
112
113 /* Structures and Functions for the Test Results Box */
114 struct trbox;
115
116 typedef void populate_trbox_func(struct trbox *trb,
117                                  struct cmd_t_test *cmd);
118 typedef void finalize_trbox_func(struct trbox *trb);
119
120 struct trbox {
121   struct tab_table *t;
122   populate_trbox_func *populate;
123   finalize_trbox_func *finalize;
124 };
125
126 /* Create a trbox */
127 void trbox_create(struct trbox *trb,   struct cmd_t_test *cmd, int mode);
128
129 /* Populate a ssbox according to cmd */
130 void trbox_populate(struct trbox *trb, struct cmd_t_test *cmd);
131
132 /* Submit and destroy a ssbox */
133 void trbox_finalize(struct trbox *trb);
134
135 /* Which mode was T-TEST invoked */
136 enum {
137   T_1_SAMPLE = 0 ,
138   T_IND_SAMPLES, 
139   T_PAIRED
140 };
141
142
143 static int common_calc (struct ccase *);
144 static void common_precalc (void);
145 static void common_postcalc (void);
146
147 static int one_sample_calc (struct ccase *);
148 static void one_sample_precalc (void);
149 static void one_sample_postcalc (void);
150
151 static int  paired_calc (struct ccase *);
152 static void paired_precalc (void);
153 static void paired_postcalc (void);
154
155 static int compare_var_name (const void *a_, const void *b_, void *v_ unused);
156 static unsigned hash_var_name (const void *a_, void *v_ unused);
157
158
159 int
160 cmd_t_test(void)
161 {
162   int mode;
163
164   struct ssbox stat_summary_box;
165   struct trbox test_results_box;
166
167   if (!lex_force_match_id ("T"))
168     return CMD_FAILURE;
169
170   lex_match ('-');
171   lex_match_id ("TEST");
172
173   if ( !parse_t_test(&cmd) )
174     return CMD_FAILURE;
175
176   if (! cmd.sbc_criteria)
177     cmd.criteria=0.95;
178
179   if ( cmd.sbc_testval + cmd.sbc_groups + cmd.sbc_pairs != 1 ) 
180     {
181       msg(SE, 
182           _("Exactly one of TESTVAL, GROUPS or PAIRS subcommands is required")
183           );
184       return CMD_FAILURE;
185     }
186
187   if (cmd.sbc_testval) 
188     mode=T_1_SAMPLE;
189   else if (cmd.sbc_groups)
190     mode=T_IND_SAMPLES;
191   else
192     mode=T_PAIRED;
193
194   if ( mode == T_PAIRED) 
195     {
196       if (cmd.sbc_variables) 
197         {
198           msg(SE, _("VARIABLES subcommand is not appropriate with PAIRS"));
199           return CMD_FAILURE;
200         }
201       else
202         {
203           /* Iterate through the pairs and put each variable that is a 
204              member of a pair into cmd.v_variables */
205
206           int i;
207           struct hsh_iterator hi;
208           struct hsh_table *hash;
209           struct variable *v;
210
211           hash=hsh_create(n_pairs,compare_var_name,hash_var_name,0,0);
212
213           for (i=0; i < n_pairs; ++i)
214             {
215               hsh_insert(hash,pairs[i].v[0]);
216               hsh_insert(hash,pairs[i].v[1]);
217             }
218
219           assert(cmd.n_variables == 0);
220           cmd.n_variables = hsh_count(hash);
221
222           cmd.v_variables = xrealloc(cmd.v_variables,
223                                      sizeof(struct variable) * cmd.n_variables);
224           /* Iterate through the hash */
225           for (i=0,v = (struct variable *) hsh_first(hash,&hi);
226                v != 0;
227                v=hsh_next(hash,&hi) ) 
228             cmd.v_variables[i++]=v;
229
230           hsh_destroy(hash);
231         }
232     }
233
234
235   procedure(common_precalc,common_calc,common_postcalc);
236
237   switch(mode)
238     {
239     case T_1_SAMPLE:
240       procedure(one_sample_precalc,one_sample_calc,one_sample_postcalc);
241       break;
242     case T_PAIRED:
243       procedure(paired_precalc,paired_calc,paired_postcalc);
244       break;
245     }
246   
247
248   t_test_pool = pool_create ();
249
250   ssbox_create(&stat_summary_box,&cmd,mode);
251   ssbox_populate(&stat_summary_box,&cmd);
252   ssbox_finalize(&stat_summary_box);
253
254   if ( mode == T_PAIRED) 
255     {
256       pscbox(&cmd);
257     }
258
259   trbox_create(&test_results_box,&cmd,mode);
260   trbox_populate(&test_results_box,&cmd);
261   trbox_finalize(&test_results_box);
262
263   pool_destroy (t_test_pool);
264
265   t_test_pool=0;
266     
267   return CMD_SUCCESS;
268 }
269
270 static int
271 tts_custom_groups (struct cmd_t_test *cmd unused)
272 {
273   lex_match('=');
274
275   if (token != T_ALL && 
276       (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
277      ) 
278   {
279     msg(SE,_("`%s' is not a variable name"),tokid);
280     return 0;
281   }
282
283   groups = parse_variable ();
284   if (!groups)
285     {
286       lex_error ("expecting variable name in GROUPS subcommand");
287       return 0;
288     }
289
290   if (groups->type == T_STRING && groups->width > MAX_SHORT_STRING)
291     {
292       msg (SE, _("Long string variable %s is not valid here."),
293            groups->name);
294       return 0;
295     }
296
297   if (!lex_match ('('))
298     {
299       if (groups->type == NUMERIC)
300         {
301           n_groups_values = 2;
302           groups_values[0].f = 1;
303           groups_values[1].f = 2;
304           return 1;
305         }
306       else
307         {
308           msg (SE, _("When applying GROUPS to a string variable, at "
309                      "least one value must be specified."));
310           return 0;
311         }
312     }
313
314   if (!parse_value (&groups_values[0],groups->type))
315     return 0;
316   n_groups_values = 1;
317
318   lex_match (',');
319   if (lex_match (')'))
320     return 1;
321
322   if (!parse_value (&groups_values[1],groups->type))
323     return 0;
324   n_groups_values = 2;
325
326   if (!lex_force_match (')'))
327     return 0;
328
329   return 1;
330 }
331
332
333
334
335 static int
336 tts_custom_pairs (struct cmd_t_test *cmd unused)
337 {
338   struct variable **vars;
339   int n_vars;
340
341   int n_before_WITH ;
342   int n_after_WITH = -1;
343   int paired ; /* Was the PAIRED keyword given ? */
344
345   lex_match('=');
346
347   if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
348       && token != T_ALL)
349     {
350       msg(SE,_("`%s' is not a variable name"),tokid);
351       return 0;
352     }
353
354   n_vars=0;
355   if (!parse_variables (default_dict, &vars, &n_vars,
356                         PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
357     {
358       free (vars);
359       return 0;
360     }
361   assert (n_vars);
362
363   n_before_WITH=0;
364   if (lex_match (T_WITH))
365     {
366       n_before_WITH = n_vars;
367       if (!parse_variables (default_dict, &vars, &n_vars,
368                             PV_DUPLICATE | PV_APPEND
369                             | PV_NUMERIC | PV_NO_SCRATCH))
370         {
371           free (vars);
372           return 0;
373         }
374       n_after_WITH = n_vars - n_before_WITH;
375     }
376
377   paired = (lex_match ('(') && lex_match_id ("PAIRED") && lex_match (')'));
378
379   /* Determine the number of pairs needed */
380   if (paired)
381     {
382       if (n_before_WITH != n_after_WITH)
383         {
384           free (vars);
385           msg (SE, _("PAIRED was specified but the number of variables "
386                      "preceding WITH (%d) did not match the number "
387                      "following (%d)."),
388                n_before_WITH, n_after_WITH );
389           return 0;
390         }
391       n_pairs=n_before_WITH;
392     }
393   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
394     {
395       n_pairs=n_before_WITH * n_after_WITH ;
396     }
397   else /* Neither WITH nor PAIRED keyword given */
398     {
399       if (n_vars < 2)
400         {
401           free (vars);
402           msg (SE, _("At least two variables must be specified "
403                      "on PAIRS."));
404           return 0;
405         }
406
407       /* how many ways can you pick 2 from n_vars ? */
408       n_pairs = n_vars * (n_vars -1 ) /2 ;
409     }
410
411   /* Allocate storage for the pairs */
412   pairs = xrealloc(pairs,sizeof(struct pair) *n_pairs);
413
414   /* Populate the pairs with the appropriate variables */
415   if ( paired ) 
416     {
417       int i;
418
419       assert(n_pairs == n_vars/2);
420       for (i = 0; i < n_pairs ; ++i)
421         {
422           pairs[i].v[0] = vars[i];
423           pairs[i].v[1] = vars[i+n_pairs];
424         }
425     }
426   else if (n_before_WITH > 0) /* WITH keyword given, but not PAIRED keyword */
427     {
428       int i,j;
429       int p=0;
430
431       for(i=0 ; i < n_before_WITH ; ++i ) 
432         {
433           for(j=0 ; j < n_after_WITH ; ++j)
434             {
435               pairs[p].v[0] = vars[i];
436               pairs[p].v[1] = vars[j+n_before_WITH];
437               ++p;
438             }
439         }
440     }
441   else /* Neither WITH nor PAIRED given */
442     {
443       int i,j;
444       int p=0;
445       
446       for(i=0 ; i < n_vars ; ++i ) 
447         {
448           for(j=i+1 ; j < n_vars ; ++j)
449             {
450               pairs[p].v[0] = vars[i];
451               pairs[p].v[1] = vars[j];
452               ++p;
453             }
454         }
455     }
456
457   return 1;
458 }
459
460 /* Parses the current token (numeric or string, depending on type)
461     value v and returns success. */
462 static int
463 parse_value (union value * v, int type )
464 {
465   if (type == NUMERIC)
466     {
467       if (!lex_force_num ())
468         return 0;
469       v->f = tokval;
470     }
471   else
472     {
473       if (!lex_force_string ())
474         return 0;
475       strncpy (v->s, ds_value (&tokstr), ds_length (&tokstr));
476     }
477
478   lex_get ();
479
480   return 1;
481 }
482
483
484 /* Implementation of the SSBOX object */
485
486 void ssbox_base_init(struct ssbox *this, int cols,int rows);
487
488 void ssbox_base_finalize(struct ssbox *ssb);
489
490 void ssbox_one_sample_init(struct ssbox *this, 
491                            struct cmd_t_test *cmd );
492
493 void ssbox_independent_samples_init(struct ssbox *this,
494                                     struct cmd_t_test *cmd);
495
496 void ssbox_paired_init(struct ssbox *this,
497                            struct cmd_t_test *cmd);
498
499 /* Factory to create an ssbox */
500 void 
501 ssbox_create(struct ssbox *ssb, struct cmd_t_test *cmd, int mode)
502 {
503     switch (mode) 
504       {
505       case T_1_SAMPLE:
506         ssbox_one_sample_init(ssb,cmd);
507         break;
508       case T_IND_SAMPLES:
509         ssbox_independent_samples_init(ssb,cmd);
510         break;
511       case T_PAIRED:
512         ssbox_paired_init(ssb,cmd);
513         break;
514       default:
515         assert(0);
516       }
517 }
518
519
520 /* Despatcher for the populate method */
521 void
522 ssbox_populate(struct ssbox *ssb,struct cmd_t_test *cmd)
523 {
524   ssb->populate(ssb,cmd);
525 }
526
527
528 /* Despatcher for finalize */
529 void
530 ssbox_finalize(struct ssbox *ssb)
531 {
532   ssb->finalize(ssb);
533 }
534
535
536 /* Submit the box and clear up */
537 void 
538 ssbox_base_finalize(struct ssbox *ssb)
539 {
540   tab_submit(ssb->t);
541 }
542
543 /* Initialize a ssbox struct */
544 void 
545 ssbox_base_init(struct ssbox *this, int cols,int rows)
546 {
547   this->finalize = ssbox_base_finalize;
548   this->t = tab_create (cols, rows, 0);
549
550   tab_columns (this->t, SOM_COL_DOWN, 1);
551   tab_headers (this->t,0,0,1,0); 
552   tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
553   tab_hline(this->t, TAL_2,0,cols-1,1);
554   tab_dim (this->t, tab_natural_dimensions);
555 }
556
557 void  ssbox_one_sample_populate(struct ssbox *ssb,
558                               struct cmd_t_test *cmd);
559
560 /* Initialize the one_sample ssbox */
561 void 
562 ssbox_one_sample_init(struct ssbox *this, 
563                            struct cmd_t_test *cmd )
564 {
565   const int hsize=5;
566   const int vsize=cmd->n_variables+1;
567
568   this->populate = ssbox_one_sample_populate;
569
570   ssbox_base_init(this, hsize,vsize);
571   tab_title (this->t, 0, _("One-Sample Statistics"));
572   tab_vline(this->t, TAL_2, 1,0,vsize);
573   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, _("N"));
574   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
575   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
576   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
577 }
578
579 void ssbox_independent_samples_populate(struct ssbox *ssb,
580                                         struct cmd_t_test *cmd);
581
582 /* Initialize the independent samples ssbox */
583 void 
584 ssbox_independent_samples_init(struct ssbox *this, 
585         struct cmd_t_test *cmd)
586 {
587   int hsize=6;
588   int vsize = cmd->n_variables*2 +1;
589
590   this->populate = ssbox_independent_samples_populate;
591
592   ssbox_base_init(this, hsize,vsize);
593   tab_title (this->t, 0, _("Group Statistics"));
594   tab_vline(this->t,0,1,0,vsize);
595   tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, groups->name);
596   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
597   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
598   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
599   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
600 }
601
602
603 /* Populate the ssbox for independent samples */
604 void 
605 ssbox_independent_samples_populate(struct ssbox *ssb,
606                               struct cmd_t_test *cmd)
607 {
608   int i;
609
610   char *val_lab1=0;
611   char *val_lab2=0;
612
613   if ( groups->type == NUMERIC ) 
614     {
615       val_lab1 = val_labs_find( groups->val_labs,groups_values[0]); 
616       val_lab2 = val_labs_find( groups->val_labs,groups_values[1]);
617     }
618   else
619     {
620       val_lab1 = groups_values[0].s;
621       val_lab2 = groups_values[1].s;
622     }
623
624   assert(ssb->t);
625
626   for (i=0; i < cmd->n_variables; ++i)
627     {
628       tab_text (ssb->t, 0, i*2+1, TAB_LEFT, cmd->v_variables[i]->name);
629
630       if (val_lab1)
631         tab_text (ssb->t, 1, i*2+1, TAB_LEFT, val_lab1);
632       else
633         tab_float(ssb->t, 1 ,i*2+1, TAB_LEFT, groups_values[0].f, 2,0);
634
635       if (val_lab2)
636         tab_text (ssb->t, 1, i*2+1+1, TAB_LEFT, val_lab2);
637       else
638         tab_float(ssb->t, 1 ,i*2+1+1, TAB_LEFT, groups_values[1].f,2,0);
639     }
640 }
641
642
643 void ssbox_paired_populate(struct ssbox *ssb,
644                            struct cmd_t_test *cmd);
645
646 /* Initialize the paired values ssbox */
647 void 
648 ssbox_paired_init(struct ssbox *this, struct cmd_t_test *cmd unused)
649 {
650   int hsize=6;
651
652   int vsize = n_pairs*2+1;
653
654   this->populate = ssbox_paired_populate;
655
656   ssbox_base_init(this, hsize,vsize);
657   tab_title (this->t, 0, _("Paired Sample Statistics"));
658   tab_vline(this->t,TAL_0,1,0,vsize-1);
659   tab_vline(this->t,TAL_2,2,0,vsize-1);
660   tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
661   tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("N"));
662   tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
663   tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("SE. Mean"));
664 }
665
666
667 /* Populate the ssbox for paired values */
668 void 
669 ssbox_paired_populate(struct ssbox *ssb,struct cmd_t_test *cmd unused)
670 {
671   int i;
672
673   assert(ssb->t);
674
675   for (i=0; i < n_pairs; ++i)
676     {
677       int j;
678
679       tab_text (ssb->t, 0, i*2+1, TAB_LEFT | TAT_PRINTF , _("Pair %d"),i);
680
681       for (j=0 ; j < 2 ; ++j) 
682         {
683           struct t_test_proc *ttp;
684
685           ttp=&pairs[i].v[j]->p.t_t;
686
687           /* Titles */
688
689           tab_text (ssb->t, 1, i*2+j+1, TAB_LEFT, pairs[i].v[j]->name);
690
691           /* Values */
692           tab_float (ssb->t,2, i*2+j+1, TAB_RIGHT, ttp->mean, 8, 2);
693           tab_float (ssb->t,3, i*2+j+1, TAB_RIGHT, ttp->n, 2, 0);
694           tab_float (ssb->t,4, i*2+j+1, TAB_RIGHT, ttp->std_dev, 8, 3);
695           tab_float (ssb->t,5, i*2+j+1, TAB_RIGHT, ttp->se_mean, 8, 3);
696
697         }
698
699     }
700
701 }
702
703 /* Populate the one sample ssbox */
704 void 
705 ssbox_one_sample_populate(struct ssbox *ssb, struct cmd_t_test *cmd)
706 {
707   int i;
708
709   assert(ssb->t);
710
711   for (i=0; i < cmd->n_variables; ++i)
712     {
713       struct t_test_proc *ttp;
714       ttp= &cmd->v_variables[i]->p.t_t;
715
716       tab_text (ssb->t, 0, i+1, TAB_LEFT, cmd->v_variables[i]->name);
717       tab_float (ssb->t,1, i+1, TAB_RIGHT, ttp->n, 2, 0);
718       tab_float (ssb->t,2, i+1, TAB_RIGHT, ttp->mean, 8, 2);
719       tab_float (ssb->t,3, i+1, TAB_RIGHT, ttp->std_dev, 8, 2);
720       tab_float (ssb->t,4, i+1, TAB_RIGHT, ttp->se_mean, 8, 3);
721     }
722   
723 }
724
725
726
727 /* Implementation of the Test Results box struct */
728
729 void trbox_base_init(struct trbox *self,int n_vars, int cols);
730 void trbox_base_finalize(struct trbox *trb);
731
732 void trbox_independent_samples_init(struct trbox *trb,
733                                     struct cmd_t_test *cmd );
734
735 void trbox_independent_samples_populate(struct trbox *trb,
736                                         struct cmd_t_test *cmd);
737
738 void trbox_one_sample_init(struct trbox *self,
739                       struct cmd_t_test *cmd );
740
741 void trbox_one_sample_populate(struct trbox *trb,
742                                struct cmd_t_test *cmd);
743
744 void trbox_paired_init(struct trbox *self,
745                        struct cmd_t_test *cmd );
746
747 void trbox_paired_populate(struct trbox *trb,
748                       struct cmd_t_test *cmd);
749
750
751
752 /* Create a trbox according to mode*/
753 void 
754 trbox_create(struct trbox *trb,   
755              struct cmd_t_test *cmd, int mode)
756 {
757     switch (mode) 
758       {
759       case T_1_SAMPLE:
760         trbox_one_sample_init(trb,cmd);
761         break;
762       case T_IND_SAMPLES:
763         trbox_independent_samples_init(trb,cmd);
764         break;
765       case T_PAIRED:
766         trbox_paired_init(trb,cmd);
767         break;
768       default:
769         assert(0);
770       }
771 }
772
773 /* Populate a trbox according to cmd */
774 void 
775 trbox_populate(struct trbox *trb, struct cmd_t_test *cmd)
776 {
777   trb->populate(trb,cmd);
778 }
779
780 /* Submit and destroy a trbox */
781 void 
782 trbox_finalize(struct trbox *trb)
783 {
784   trb->finalize(trb);
785 }
786
787 /* Initialize the independent samples trbox */
788 void 
789 trbox_independent_samples_init(struct trbox *self,
790                            struct cmd_t_test *cmd unused)
791 {
792   const int hsize=11;
793   const int vsize=cmd->n_variables*2+3;
794
795   assert(self);
796   self->populate = trbox_independent_samples_populate;
797
798   trbox_base_init(self,cmd->n_variables*2,hsize);
799   tab_title(self->t,0,_("Independent Samples Test"));
800   tab_hline(self->t,TAL_1,2,hsize-1,1);
801   tab_vline(self->t,TAL_2,2,0,vsize-1);
802   tab_vline(self->t,TAL_1,4,0,vsize-1);
803   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,hsize-2,vsize-1);
804   tab_hline(self->t,TAL_1, hsize-2,hsize-1,2);
805   tab_box(self->t,-1,-1,-1,TAL_1, hsize-2,2,hsize-1,vsize-1);
806   tab_joint_text(self->t, 2, 0, 3, 0, 
807                  TAB_CENTER,_("Levine's Test for Equality of Variances"));
808   tab_joint_text(self->t, 4,0,hsize-1,0,
809                  TAB_CENTER,_("t-test for Equality of Means"));
810
811   tab_text(self->t,2,2, TAB_CENTER | TAT_TITLE,_("F"));
812   tab_text(self->t,3,2, TAB_CENTER | TAT_TITLE,_("Sig."));
813   tab_text(self->t,4,2, TAB_CENTER | TAT_TITLE,_("t"));
814   tab_text(self->t,5,2, TAB_CENTER | TAT_TITLE,_("df"));
815   tab_text(self->t,6,2, TAB_CENTER | TAT_TITLE,_("Sig. (2-tailed)"));
816   tab_text(self->t,7,2, TAB_CENTER | TAT_TITLE,_("Mean Difference"));
817   tab_text(self->t,8,2, TAB_CENTER | TAT_TITLE,_("Std. Error Difference"));
818   tab_text(self->t,9,2, TAB_CENTER | TAT_TITLE,_("Lower"));
819   tab_text(self->t,10,2, TAB_CENTER | TAT_TITLE,_("Upper"));
820
821   tab_joint_text(self->t, 9, 1, 10, 1, TAB_CENTER | TAT_PRINTF, 
822                  _("%d%% Confidence Interval of the Difference"),
823                  (int)round(cmd->criteria*100.0));
824
825 }
826
827 /* Populate the independent samples trbox */
828 void 
829 trbox_independent_samples_populate(struct trbox *self,
830                                    struct cmd_t_test *cmd )
831 {
832   int i;
833
834   assert(self);
835   for (i=0; i < cmd->n_variables; ++i)
836     {
837       tab_text (self->t, 0, i*2+3, TAB_LEFT, cmd->v_variables[i]->name);
838
839       tab_text (self->t, 1, i*2+3, TAB_LEFT, _("Equal variances assumed"));
840
841       tab_text (self->t, 1, i*2+3+1, 
842                 TAB_LEFT, _("Equal variances not assumed"));
843     }
844 }
845
846 /* Initialize the paired samples trbox */
847 void 
848 trbox_paired_init(struct trbox *self,
849                            struct cmd_t_test *cmd unused)
850 {
851
852   const int hsize=10;
853   const int vsize=n_pairs*2+3;
854
855   self->populate = trbox_paired_populate;
856
857   trbox_base_init(self,n_pairs*2,hsize);
858   tab_title (self->t, 0, _("Paired Samples Test"));
859   tab_hline(self->t,TAL_1,2,6,1);
860   tab_vline(self->t,TAL_2,2,0,vsize);
861   tab_joint_text(self->t,2,0,6,0,TAB_CENTER,_("Paired Differences"));
862   tab_box(self->t,-1,-1,-1,TAL_1, 2,1,6,vsize-1);
863   tab_box(self->t,-1,-1,-1,TAL_1, 6,0,hsize-1,vsize-1);
864   tab_hline(self->t,TAL_1,5,6, 2);
865   tab_vline(self->t,TAL_0,6,0,1);
866
867   tab_joint_text(self->t, 5, 1, 6, 1, TAB_CENTER | TAT_PRINTF, 
868                  _("%d%% Confidence Interval of the Difference"),
869                  (int)round(cmd->criteria*100.0));
870
871   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("Mean"));
872   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
873   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Mean"));
874   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
875   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
876   tab_text (self->t, 7, 2, TAB_CENTER | TAT_TITLE, _("t"));
877   tab_text (self->t, 8, 2, TAB_CENTER | TAT_TITLE, _("df"));
878   tab_text (self->t, 9, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
879 }
880
881 /* Populate the paired samples trbox */
882 void 
883 trbox_paired_populate(struct trbox *trb,
884                               struct cmd_t_test *cmd unused)
885 {
886   int i;
887
888   for (i=0; i < n_pairs; ++i)
889     {
890       tab_text (trb->t, 0, i*2+3, TAB_LEFT | TAT_PRINTF, _("Pair %d"),i); 
891       tab_text (trb->t, 1, i*2+3, TAB_LEFT, pairs[i].v[0]->name);
892       tab_text (trb->t, 1, i*2+4, TAB_LEFT, pairs[i].v[1]->name);
893     }
894
895 }
896
897 /* Initialize the one sample trbox */
898 void 
899 trbox_one_sample_init(struct trbox *self, struct cmd_t_test *cmd )
900 {
901   const int hsize=7;
902   const int vsize=cmd->n_variables+3;
903
904   self->populate = trbox_one_sample_populate;
905
906   trbox_base_init(self, cmd->n_variables,hsize);
907   tab_title (self->t, 0, _("One-Sample Test"));
908   tab_hline(self->t, TAL_1, 1, hsize - 1, 1);
909   tab_vline(self->t, TAL_2, 1, 0, vsize);
910
911   tab_joint_text(self->t, 1, 0, hsize-1,0, TAB_CENTER | TAT_PRINTF, 
912                  _("Test Value = %f"),cmd->n_testval);
913
914   tab_box(self->t, -1, -1, -1, TAL_1, 1,1,hsize-1,vsize-1);
915
916
917   tab_joint_text(self->t,5,1,6,1,TAB_CENTER  | TAT_PRINTF, 
918                  _("%d%% Confidence Interval of the Difference"),
919                  (int)round(cmd->criteria*100.0));
920
921   tab_vline(self->t,TAL_0,6,1,1);
922   tab_hline(self->t,TAL_1,5,6,2);
923   tab_text (self->t, 1, 2, TAB_CENTER | TAT_TITLE, _("t"));
924   tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("df"));
925   tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
926   tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
927   tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
928   tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
929
930 }
931
932
933 /* Populate the one sample trbox */
934 void 
935 trbox_one_sample_populate(struct trbox *trb, struct cmd_t_test *cmd)
936 {
937   int i;
938
939   assert(trb->t);
940
941   for (i=0; i < cmd->n_variables; ++i)
942     {
943       int which =1;
944       double t;
945       double p,q;
946       double df;
947       int status;
948       double bound;
949       struct t_test_proc *ttp;
950       ttp= &cmd->v_variables[i]->p.t_t;
951
952
953       tab_text (trb->t, 0, i+3, TAB_LEFT, cmd->v_variables[i]->name);
954
955       t = (ttp->mean - cmd->n_testval ) * sqrt(ttp->n) / ttp->std_dev ;
956
957       tab_float (trb->t, 1, i+3, TAB_RIGHT, t, 8,3);
958
959       /* degrees of freedom */
960       df = ttp->n - 1;
961
962       tab_float (trb->t, 2, i+3, TAB_RIGHT, df, 8,0);
963
964       cdft(&which, &p, &q, &t, &df, &status, &bound);
965
966       if ( 0 != status )
967         {
968           msg( SE, _("Error calculating T statistic (cdft returned %d)."),status);
969         }
970
971
972       /* Multiply by 2 to get 2-tailed significance */
973       tab_float (trb->t, 3, i+3, TAB_RIGHT, q*2.0, 8,3);
974
975       tab_float (trb->t, 4, i+3, TAB_RIGHT, ttp->mean_diff, 8,3);
976
977
978       q = (1 - cmd->criteria)/2.0;  /* 2-tailed test */
979       p = 1 - q ;
980       which=2; /* Calc T from p,q and df */
981       cdft(&which, &p, &q, &t, &df, &status, &bound);
982       if ( 0 != status )
983         {
984           msg( SE, _("Error calculating T statistic (cdft returned %d)."),status);
985         }
986
987       tab_float (trb->t, 5, i+3, TAB_RIGHT,
988                  ttp->mean_diff - t * ttp->se_mean, 8,4);
989
990       tab_float (trb->t, 6, i+3, TAB_RIGHT,
991                  ttp->mean_diff + t * ttp->se_mean, 8,4);
992     }
993 }
994
995 /* Base initializer for the generalized trbox */
996 void 
997 trbox_base_init(struct trbox *self, int data_rows, int cols)
998 {
999   const int rows = 3 + data_rows;
1000
1001   self->finalize = trbox_base_finalize;
1002   self->t = tab_create (cols, rows, 0);
1003   tab_headers (self->t,0,0,3,0); 
1004   tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols -1, rows -1);
1005   tab_hline(self->t, TAL_2,0,cols-1,3);
1006   tab_dim (self->t, tab_natural_dimensions);
1007 }
1008
1009
1010 /* Base finalizer for the trbox */
1011 void 
1012 trbox_base_finalize(struct trbox *trb)
1013 {
1014   tab_submit(trb->t);
1015 }
1016
1017
1018 /* Create , populate and submit the Paired Samples Correlation box */
1019 void
1020 pscbox(struct cmd_t_test *cmd)
1021 {
1022   const int rows=1+n_pairs;
1023   const int cols=5;
1024   int i;
1025   
1026   struct tab_table *table;
1027   
1028   table = tab_create (cols,rows,0);
1029
1030   tab_columns (table, SOM_COL_DOWN, 1);
1031   tab_headers (table,0,0,1,0); 
1032   tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
1033   tab_hline(table, TAL_2, 0, cols - 1, 1);
1034   tab_vline(table, TAL_2, 2, 0, rows - 1);
1035   tab_dim(table, tab_natural_dimensions);
1036   tab_title(table, 0, _("Paired Samples Correlations"));
1037
1038   /* column headings */
1039   tab_text(table, 2,0, TAB_CENTER | TAT_TITLE, _("N"));
1040   tab_text(table, 3,0, TAB_CENTER | TAT_TITLE, _("Correlation"));
1041   tab_text(table, 4,0, TAB_CENTER | TAT_TITLE, _("Sig."));
1042
1043
1044   for (i=0; i < n_pairs; ++i)
1045     {
1046       int which =1;
1047       double p,q;
1048
1049       int status;
1050       double bound;
1051
1052       const double df = pairs[i].v[0]->p.t_t.n -2;
1053
1054       double correlation_t = 
1055         pairs[i].correlation * sqrt(df) /
1056         sqrt(1 - sqr(pairs[i].correlation));
1057         
1058
1059       /* row headings */
1060       tab_text(table, 0,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF, 
1061                _("Pair %d"), i);
1062       
1063       tab_text(table, 1,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF, 
1064                _("%s & %s"), pairs[i].v[0]->name, pairs[i].v[1]->name);
1065
1066
1067       /* row data */
1068       tab_float(table, 3, i+1, TAB_RIGHT, pairs[i].correlation, 8, 3);
1069       tab_float(table, 2, i+1, TAB_RIGHT, pairs[i].v[0]->p.t_t.n , 4, 0);
1070
1071
1072       cdft(&which, &p, &q, &correlation_t, &df, &status, &bound);
1073
1074       if ( 0 != status )
1075         {
1076           msg( SE, _("Error calculating T statistic (cdft returned %d)."),status);
1077         }
1078
1079
1080       tab_float(table, 4, i+1, TAB_RIGHT, q*2.0, 8, 3);
1081
1082
1083       
1084     }
1085
1086   tab_submit(table);
1087 }
1088
1089
1090
1091 /* Calculation Implementation */
1092
1093 /* Per case calculations common to all variants of the T test */
1094 static int 
1095 common_calc (struct ccase *c)
1096 {
1097   int i;
1098
1099   double weight = dict_get_case_weight(default_dict,c);
1100
1101   for(i=0; i< cmd.n_variables ; ++i) 
1102     {
1103       struct t_test_proc *ttp;
1104       struct variable *v = cmd.v_variables[i];
1105       union value *val = &c->data[v->fv];
1106
1107       ttp= &cmd.v_variables[i]->p.t_t;
1108
1109       if (val->f != SYSMIS) 
1110         {
1111           ttp->n+=weight;
1112           ttp->sum+=weight * val->f;
1113           ttp->ssq+=weight * val->f * val->f;
1114         }
1115     }
1116   return 0;
1117 }
1118
1119 /* Pre calculations common to all variants of the T test */
1120 static void 
1121 common_precalc (void)
1122 {
1123   int i=0;
1124
1125   for(i=0; i< cmd.n_variables ; ++i) 
1126     {
1127       struct t_test_proc *ttp;
1128       ttp= &cmd.v_variables[i]->p.t_t;
1129       
1130       ttp->sum=0;
1131       ttp->n=0;
1132       ttp->ssq=0;
1133       ttp->sum_diff=0;
1134     }
1135 }
1136
1137 /* Post calculations common to all variants of the T test */
1138 void 
1139 common_postcalc (void)
1140 {
1141   int i=0;
1142
1143   for(i=0; i< cmd.n_variables ; ++i) 
1144     {
1145       struct t_test_proc *ttp;
1146       ttp= &cmd.v_variables[i]->p.t_t;
1147       
1148       ttp->mean=ttp->sum / ttp->n;
1149       ttp->std_dev= sqrt(
1150                          ttp->n/(ttp->n-1) *
1151                          ( (ttp->ssq / ttp->n ) - ttp->mean * ttp->mean )
1152                          ) ;
1153
1154       ttp->se_mean = ttp->std_dev / sqrt(ttp->n);
1155       ttp->mean_diff= ttp->sum_diff / ttp->n;
1156     }
1157 }
1158
1159 /* Per case calculations for one sample t test  */
1160 static int 
1161 one_sample_calc (struct ccase *c)
1162 {
1163   int i;
1164
1165   double weight = dict_get_case_weight(default_dict,c);
1166
1167   for(i=0; i< cmd.n_variables ; ++i) 
1168     {
1169       struct t_test_proc *ttp;
1170       struct variable *v = cmd.v_variables[i];
1171       union value *val = &c->data[v->fv];
1172
1173       ttp= &cmd.v_variables[i]->p.t_t;
1174       
1175       if (val->f != SYSMIS) 
1176         ttp->sum_diff += weight * (val->f - cmd.n_testval);
1177     }
1178
1179   return 0;
1180 }
1181
1182 /* Pre calculations for one sample t test */
1183 static void 
1184 one_sample_precalc (void)
1185 {
1186   int i=0;
1187   
1188   for(i=0; i< cmd.n_variables ; ++i) 
1189     {
1190       struct t_test_proc *ttp;
1191       ttp= &cmd.v_variables[i]->p.t_t;
1192       
1193       ttp->sum_diff=0;
1194     }
1195 }
1196
1197 /* Post calculations for one sample t test */
1198 static void 
1199 one_sample_postcalc (void)
1200 {
1201   int i=0;
1202   
1203   for(i=0; i< cmd.n_variables ; ++i) 
1204     {
1205       struct t_test_proc *ttp;
1206       ttp= &cmd.v_variables[i]->p.t_t;
1207
1208       
1209       ttp->mean_diff = ttp->sum_diff / ttp->n ;
1210     }
1211 }
1212
1213
1214
1215 static int
1216 compare_var_name (const void *a_, const void *b_, void *v_ unused)
1217 {
1218   const struct variable *a = a_;
1219   const struct variable *b = b_;
1220
1221   return strcmp(a->name,b->name);
1222 }
1223
1224 static unsigned
1225 hash_var_name (const void *a_, void *v_ unused)
1226 {
1227   const struct variable *a = a_;
1228
1229   return hsh_hash_bytes (a->name, strlen(a->name));
1230 }
1231
1232
1233 static void 
1234 paired_precalc (void)
1235 {
1236   int i;
1237   for(i=0; i < n_pairs ; ++i )
1238     pairs[i].correlation=0;
1239 }
1240
1241 static int  
1242 paired_calc (struct ccase *c)
1243 {
1244   int i;
1245
1246   for(i=0; i < n_pairs ; ++i )
1247     {
1248       struct variable *v0 = pairs[i].v[0];
1249       struct variable *v1 = pairs[i].v[1];
1250
1251       union value *val0 = &c->data[v0->fv];
1252       union value *val1 = &c->data[v1->fv];
1253
1254       pairs[i].correlation += ( val0->f - pairs[i].v[0]->p.t_t.mean )
1255                               *
1256                               ( val1->f - pairs[i].v[1]->p.t_t.mean );
1257     }
1258
1259
1260   return 0;
1261 }
1262
1263 static void 
1264 paired_postcalc (void)
1265 {
1266   int i;
1267
1268   for(i=0; i < n_pairs ; ++i )
1269     {
1270       
1271       pairs[i].correlation /= pairs[i].v[0]->p.t_t.std_dev * 
1272                               pairs[i].v[1]->p.t_t.std_dev ;
1273
1274       pairs[i].correlation /= pairs[i].v[0]->p.t_t.n -1; 
1275     }
1276 }