Changed the definition of factors to be self referential.
[pspp-builds.git] / src / oneway.q
index dbbd79fb55bcd5de0c1d6f4257c8e566b76089a3..ff6b79b66e9d322eac109ce062ac5806cf8bfef5 100644 (file)
@@ -84,16 +84,23 @@ static int ostensible_number_of_groups=-1;
 static is_missing_func value_is_missing;
 
 
-static void calculate(const struct casefile *cf, void *_mode);
+static void run_oneway(const struct casefile *cf, void *_mode);
 
 
 /* Routines to show the output tables */
 static void show_anova_table(void);
 static void show_descriptives(void);
 static void show_homogeneity(void);
-static void show_contrast_coeffs(void);
-static void show_contrast_tests(void);
 
+static void show_contrast_coeffs(short *);
+static void show_contrast_tests(short *);
+
+
+enum stat_table_t {STAT_DESC = 1, STAT_HOMO = 2};
+
+static enum stat_table_t stat_tables ;
+
+void output_oneway(void);
 
 
 int
@@ -110,7 +117,40 @@ cmd_oneway(void)
   else
     value_is_missing = is_missing;
 
-  multipass_procedure_with_splits (calculate, &cmd);
+  /* What statistics were requested */
+  if ( cmd.sbc_statistics ) 
+    {
+
+      for (i = 0 ; i < ONEWAY_ST_count ; ++i ) 
+       {
+         if  ( ! cmd.a_statistics[i]  ) continue;
+
+         switch (i) {
+         case ONEWAY_ST_DESCRIPTIVES:
+           stat_tables |= STAT_DESC;
+           break;
+         case ONEWAY_ST_HOMOGENEITY:
+           stat_tables |= STAT_HOMO;
+           break;
+         }
+       }
+    }
+
+  multipass_procedure_with_splits (run_oneway, &cmd);
+
+
+  return CMD_SUCCESS;
+}
+
+
+void
+output_oneway(void)
+{
+
+  int i;
+  short *bad_contrast ; 
+
+  bad_contrast = xmalloc ( sizeof (short) * cmd.sbc_contrast );
 
   /* Check the sanity of the given contrast values */
   for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
@@ -118,12 +158,14 @@ cmd_oneway(void)
       int j;
       double sum = 0;
 
+      bad_contrast[i] = 0;
       if ( subc_list_double_count(&cmd.dl_contrast[i]) != 
           ostensible_number_of_groups )
        {
-         msg(SE
+         msg(SW
              _("Number of contrast coefficients must equal the number of groups"));
-         return CMD_FAILURE;
+         bad_contrast[i] = 1;
+         continue;
        }
 
       for (j=0; j < ostensible_number_of_groups ; ++j )
@@ -133,36 +175,23 @@ cmd_oneway(void)
        msg(SW,_("Coefficients for contrast %d do not total zero"),i + 1);
     }
 
+  if ( stat_tables & STAT_DESC ) 
+    show_descriptives();
 
-
-  /* Show the statistics tables */
-  if ( cmd.sbc_statistics ) 
-    {
-    for (i = 0 ; i < ONEWAY_ST_count ; ++i ) 
-      {
-       if  ( ! cmd.a_statistics[i]  ) continue;
-
-       switch (i) {
-       case ONEWAY_ST_DESCRIPTIVES:
-         show_descriptives();
-         break;
-       case ONEWAY_ST_HOMOGENEITY:
-         show_homogeneity();
-         break;
-       }
-      }
-  }
-
+  if ( stat_tables & STAT_HOMO )
+    show_homogeneity();
 
   show_anova_table();
      
-  if (cmd.sbc_contrast)
+  if (cmd.sbc_contrast )
     {
-      show_contrast_coeffs();
-      show_contrast_tests();
+      show_contrast_coeffs(bad_contrast);
+      show_contrast_tests(bad_contrast);
     }
 
 
+  free(bad_contrast);
+
   /* Clean up */
   for (i = 0 ; i < n_vars ; ++i ) 
     {
@@ -173,13 +202,11 @@ cmd_oneway(void)
 
   hsh_destroy(global_group_hash);
 
-  return CMD_SUCCESS;
 }
 
 
 
 
-
 /* Parser for the variables sub command */
 static int
 oneway_custom_variables(struct cmd_oneway *cmd UNUSED)
@@ -526,19 +553,23 @@ show_homogeneity(void)
 
   for ( v=0 ; v < n_vars ; ++v ) 
     {
-      char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name;
-      struct group_statistics *totals = &vars[v]->p.grp_data.ugs;
-
-      const double df1 = vars[v]->p.grp_data.n_groups - 1;
-      const double df2 = totals->n - vars[v]->p.grp_data.n_groups ;
+      double F;
+      const struct variable *var = vars[v];
+      const char *s = (var->label) ? var->label : var->name;
+      const struct group_statistics *totals = &var->p.grp_data.ugs;
 
+      const double df1 = var->p.grp_data.n_groups - 1;
+      const double df2 = totals->n - var->p.grp_data.n_groups ;
 
       tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s);
 
-
-
+      F = var->p.grp_data.levene;
+      tab_float (t, 1, v + 1, TAB_RIGHT, F, 8,3);
       tab_float (t, 2, v + 1, TAB_RIGHT, df1 ,8,0);
       tab_float (t, 3, v + 1, TAB_RIGHT, df2 ,8,0);
+
+      /* Now the significance */
+      tab_float (t, 4, v + 1, TAB_RIGHT,gsl_cdf_fdist_Q(F,df1,df2), 8, 3);
     }
 
   tab_submit (t);
@@ -549,7 +580,7 @@ show_homogeneity(void)
 
 /* Show the contrast coefficients table */
 static void 
-show_contrast_coeffs(void)
+show_contrast_coeffs(short *bad_contrast)
 {
   char *s;
   int n_cols = 2 + ostensible_number_of_groups;
@@ -609,6 +640,7 @@ show_contrast_coeffs(void)
       int i;
       char *lab;
 
+
       lab = val_labs_find(indep_var->val_labs,*group_value);
   
       if ( lab ) 
@@ -620,10 +652,15 @@ show_contrast_coeffs(void)
 
       for (i = 0 ; i < cmd.sbc_contrast ; ++i ) 
        {
+
          tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1);
-         tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
-                  subc_list_double_at(&cmd.dl_contrast[i],count)
-                  );
+
+         if ( bad_contrast[i] ) 
+           tab_text(t, count + 2, i + 2, TAB_RIGHT, "?" );
+         else
+           tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", 
+                    subc_list_double_at(&cmd.dl_contrast[i],count)
+                    );
        }
          
       count++ ; 
@@ -636,7 +673,7 @@ show_contrast_coeffs(void)
 
 /* Show the results of the contrast tests */
 static void 
-show_contrast_tests(void)
+show_contrast_tests(short *bad_contrast)
 {
   int v;
   int n_cols = 8;
@@ -734,6 +771,10 @@ show_contrast_tests(void)
          tab_text (t,  2, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
                    TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1);
 
+
+         if ( bad_contrast[i]) 
+           continue;
+
          /* FIXME: Potential danger here.
             We're ASSUMING THE array is in the order corresponding to the 
             hash order. */
@@ -757,17 +798,15 @@ show_contrast_tests(void)
            }
          sec_vneq = sqrt(sec_vneq);
 
-
          df_numerator = pow2(df_numerator);
-         
 
          tab_float (t,  3, (v * lines_per_variable) + i + 1, 
                     TAB_RIGHT, contrast_value, 8,2);
 
-         tab_float (t,  3, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
+         tab_float (t,  3, (v * lines_per_variable) + i + 1 + 
+                    cmd.sbc_contrast,
                     TAB_RIGHT, contrast_value, 8,2);
 
-
          std_error_contrast = sqrt(vars[v]->p.grp_data.mse * coef_msq);
 
          /* Std. Error */
@@ -868,7 +907,6 @@ precalc ( struct cmd_oneway *cmd UNUSED )
                   (void *) indep_var->width );
 
 
-      totals->criterion = CMP_EQ;
       totals->sum=0;
       totals->n=0;
       totals->ssq=0;
@@ -880,12 +918,11 @@ precalc ( struct cmd_oneway *cmd UNUSED )
 
 
 static void 
-calculate(const struct casefile *cf, void *cmd_)
+run_oneway(const struct casefile *cf, void *cmd_)
 {
   struct casereader *r;
   struct ccase c;
 
-
   struct cmd_oneway *cmd = (struct cmd_oneway *) cmd_;
 
   global_group_hash = hsh_create(4, 
@@ -893,11 +930,8 @@ calculate(const struct casefile *cf, void *cmd_)
                                 (hsh_hash_func *) hash_value,
                                 0,
                                 (void *) indep_var->width );
-
   precalc(cmd);
 
-
-
   for(r = casefile_get_reader (cf);
       casereader_read (r, &c) ;
       case_destroy (&c)) 
@@ -908,10 +942,30 @@ calculate(const struct casefile *cf, void *cmd_)
        dict_get_case_weight(default_dict,&c,&bad_weight_warn);
       
       const union value *indep_val = case_data (&c, indep_var->fv);
+
+      /* Deal with missing values */
+      if ( value_is_missing(indep_val,indep_var) )
+          continue;
+
+      /* Skip the entire case if /MISSING=LISTWISE is set */
+      if ( cmd->miss == ONEWAY_LISTWISE ) 
+       {
+         for(i = 0; i < n_vars ; ++i) 
+           {
+             const struct variable *v = vars[i];
+             const union value *val = case_data (&c, v->fv);
+
+             if (value_is_missing(val,v) )
+                 break;
+           }
+         if ( i != n_vars ) 
+             continue;
+
+       }
+      
          
       hsh_insert ( global_group_hash, (void *) indep_val );
 
-
       for ( i = 0 ; i < n_vars ; ++i ) 
        {
          const struct variable *v = vars[i];
@@ -929,7 +983,6 @@ calculate(const struct casefile *cf, void *cmd_)
              gs = (struct group_statistics *) 
                xmalloc (sizeof(struct group_statistics));
 
-             gs->criterion = CMP_EQ;
              gs->id = *indep_val;
              gs->sum=0;
              gs->n=0;
@@ -974,12 +1027,18 @@ calculate(const struct casefile *cf, void *cmd_)
 
   postcalc(cmd);
 
-  /* 
-  levene(cf, indep_var, n_vars, vars, LEV_LISTWISE, value_is_missing);
-  */
+  
+  if ( stat_tables & STAT_HOMO ) 
+    levene(cf, indep_var, n_vars, vars, 
+          (cmd->miss == ONEWAY_LISTWISE) ? LEV_LISTWISE : LEV_ANALYSIS ,
+          value_is_missing);
 
   ostensible_number_of_groups = hsh_count (global_group_hash);
 
+
+  output_oneway();
+
+
 }
 
 
@@ -1027,8 +1086,5 @@ postcalc (  struct cmd_oneway *cmd UNUSED )
 
       totals->se_mean = totals->std_dev / sqrt(totals->n);
        
-
-
-      
     }
 }