oneway: Fix descriptives for multiple variables
authorJohn Darrington <john@darrington.wattle.id.au>
Sun, 15 Aug 2010 11:10:37 +0000 (13:10 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Tue, 24 Aug 2010 14:37:15 +0000 (16:37 +0200)
src/language/stats/glm.q
src/language/stats/oneway.c
src/math/categoricals.c
src/math/categoricals.h

index 0d792df898bd36efdbbd5e1b872f1245012401f4..4de00e3bb9450ea90848e85ead17421771f8e58e 100644 (file)
@@ -362,7 +362,7 @@ run_glm (struct casereader *input,
   struct categoricals *cats =
     categoricals_create (categoricals, n_categoricals,
                         NULL, MV_NEVER,
-                        NULL, NULL, NULL);
+                        NULL, NULL, NULL, NULL);
 
   cov = covariance_2pass_create (n_numerics, numerics,
                                 cats,
index f421371c1d43201c8e1112717e16ba3c266a8aa1..b2d1e5b1861307ba2e2bfd3c2f18e05c70528718 100644 (file)
@@ -99,6 +99,7 @@ struct oneway_spec
 
   /* The weight variable */
   const struct variable *wv;
+
 };
 
 
@@ -128,9 +129,8 @@ struct oneway_workspace
 
   struct per_var_ws *vws;
 
-  struct moments1 *totals;
-  double minimum;
-  double maximum;
+  /* An array of descriptive data.  One for each dependent variable */
+  struct descriptive_data **dd_total;
 };
 
 /* Routines to show the output tables */
@@ -268,8 +268,6 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
     struct casereader *group;
     bool ok;
 
-
-
     grouper = casegrouper_create_splits (proc_open (ds), dict);
     while (casegrouper_get_next_group (grouper, &group))
       run_oneway (&oneway, group, ds);
@@ -317,49 +315,76 @@ static void  precalc (const struct oneway_spec *cmd);
 
 struct descriptive_data
 {
+  const struct variable *var;
   struct moments1 *mom;
+
   double minimum;
   double maximum;
 };
 
-static void *
-makeit (void)
+static struct descriptive_data *
+dd_create (const struct variable *var)
 {
   struct descriptive_data *dd = xmalloc (sizeof *dd);
+
   dd->mom = moments1_create (MOMENT_VARIANCE);
   dd->minimum = DBL_MAX;
   dd->maximum = -DBL_MAX;
+  dd->var = var;
+
+  return dd;
+}
+
+
+static void *
+makeit (void *aux1, void *aux2 UNUSED)
+{
+  const struct variable *var = aux1;
+
+  struct descriptive_data *dd = dd_create (var);
 
   return dd;
 }
 
 static void 
 updateit (void *user_data, const struct variable *wv, 
-         const struct variable *catvar, const struct ccase *c, void *aux)
+         const struct variable *catvar UNUSED,
+         const struct ccase *c,
+         void *aux1, void *aux2)
 {
-  const union value *val = case_data_idx (c, 0);
   struct descriptive_data *dd = user_data;
-  struct oneway_workspace *ws = aux;
+
+  const struct variable *varp = aux1;
+
+  const union value *valx = case_data (c, varp);
+
+  struct descriptive_data *dd_total = aux2;
 
   double weight = 1.0;
   if (wv)
     weight = case_data (c, wv)->f;
 
-  moments1_add (dd->mom, val->f, weight);
-  moments1_add (ws->totals, val->f, weight);
+  moments1_add (dd->mom, valx->f, weight);
+  if (valx->f * weight < dd->minimum)
+    dd->minimum = valx->f * weight;
 
-  if (val->f * weight < dd->minimum)
-    dd->minimum = val->f * weight;
+  if (valx->f * weight > dd->maximum)
+    dd->maximum = valx->f * weight;
 
-  if (val->f * weight > dd->maximum)
-    dd->maximum = val->f * weight;
+  {
+    const struct variable *var = dd_total->var;
+    const union value *val = case_data (c, var);
 
+    moments1_add (dd_total->mom,
+                 val->f,
+                 weight);
 
-  if (val->f * weight < ws->minimum)
-    ws->minimum = val->f * weight;
+    if (val->f * weight < dd_total->minimum)
+      dd_total->minimum = val->f * weight;
 
-  if (val->f * weight > ws->maximum)
-    ws->maximum = val->f * weight;
+    if (val->f * weight > dd_total->maximum)
+      dd_total->maximum = val->f * weight;
+  }
 }
 
 static void
@@ -374,20 +399,25 @@ run_oneway (const struct oneway_spec *cmd,
   struct ccase *c;
 
   struct oneway_workspace ws;
+  
+  {
+    ws.vws = xmalloc (cmd->n_vars * sizeof (*ws.vws));
 
-  ws.vws = xmalloc (cmd->n_vars * sizeof (*ws.vws));
-
-  ws.totals = moments1_create (MOMENT_VARIANCE);
-  ws.minimum = DBL_MAX;
-  ws.maximum = -DBL_MAX;
+    ws.dd_total = xmalloc (sizeof (struct descriptive_data) * cmd->n_vars);
 
+    for (v = 0 ; v < cmd->n_vars; ++v)
+      {
+       ws.dd_total[v] = dd_create (cmd->vars[v]);
+      }
+  }
 
   for (v = 0; v < cmd->n_vars; ++v)
     {
       struct categoricals *cats = categoricals_create (&cmd->indep_var, 1,
                                                       cmd->wv, cmd->exclude, 
                                                       makeit,
-                                                      updateit, &ws);
+                                                      updateit,
+                                                      cmd->vars[v], ws.dd_total[v]);
 
       ws.vws[v].cov = covariance_2pass_create (1, &cmd->vars[v],
                                               cats, 
@@ -886,11 +916,13 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
       {
        double T;
        double n, mean, variance;
+       double std_dev;
+       double std_error;
 
-       moments1_calculate (ws->totals, &n, &mean, &variance, NULL, NULL);
+       moments1_calculate (ws->dd_total[v]->mom, &n, &mean, &variance, NULL, NULL);
 
-       double std_dev = sqrt (variance);
-       double std_error = std_dev / sqrt (n) ;
+       std_dev = sqrt (variance);
+       std_error = std_dev / sqrt (n) ;
 
        tab_text (t, 1, row + count,
                  TAB_LEFT | TAT_TITLE, _("Total"));
@@ -904,7 +936,6 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
        tab_double (t, 5, row + count, 0, std_error, NULL);
 
        /* Now the confidence interval */
-
        T = gsl_cdf_tdist_Qinv (q, n - 1);
 
        tab_double (t, 6, row + count, 0,
@@ -914,9 +945,8 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
                    mean + T * std_error, NULL);
 
        /* Min and Max */
-
-       tab_double (t, 8, row + count, 0,  ws->minimum, fmt);
-       tab_double (t, 9, row + count, 0,  ws->maximum, fmt);
+       tab_double (t, 8, row + count, 0,  ws->dd_total[v]->minimum, fmt);
+       tab_double (t, 9, row + count, 0,  ws->dd_total[v]->maximum, fmt);
       }
 
       row += categoricals_total (cats) + 1;
index ef9c528994428775614adedc1e59ab0949fb1ebc..1968b332f8257229d0d9cd25d4c601a3ed764426 100644 (file)
@@ -93,11 +93,14 @@ struct categoricals
   /* Function to be called on each update */
   update_func *update;
 
-  /* Auxilliary data to be passed to update */
-  void *update_aux;
 
   /* Function specified by the caller to create user_data */
   user_data_create_func *user_data_create;
+
+
+  /* Auxilliary data to be passed to update and user_data_create_func*/
+  void *aux1;
+  void *aux2;
 };
 
 
@@ -197,7 +200,7 @@ struct categoricals *
 categoricals_create (const struct variable *const *v, size_t n_vars,
                     const struct variable *wv, enum mv_class exclude,
                     user_data_create_func *udf,
-                    update_func *update, void *aux
+                    update_func *update, void *aux1, void *aux2
                     )
 {
   size_t i;
@@ -211,9 +214,12 @@ categoricals_create (const struct variable *const *v, size_t n_vars,
   cat->pool = pool_create ();
   cat->exclude = exclude;
   cat->update = update;
-  cat->update_aux = aux;
   cat->user_data_create = udf;
 
+  cat->aux1 = aux1;
+  cat->aux2 = aux2;
+
+
   cat->vp = pool_calloc (cat->pool, cat->n_vp, sizeof *cat->vp);
 
   for (i = 0 ; i < cat->n_vp; ++i)
@@ -266,15 +272,15 @@ categoricals_update (struct categoricals *cat, const struct ccase *c)
 
          node->subscript = cat->vp[i].n_cats++ ;
 
-         if ( cat->user_data_create )
-           node->user_data = cat->user_data_create ();
+         if (cat->user_data_create)
+           node->user_data = cat->user_data_create (cat->aux1, cat->aux2);
        }
 
       node->cc += weight;
       cat->vp[i].cc += weight;
 
-      if ( cat->update)
-       cat->update (node->user_data, cat->wv, var, c, cat->update_aux);
+      if (cat->update)
+       cat->update (node->user_data, cat->wv, var, c, cat->aux1, cat->aux2);
     }
 }
 
index ff33540ca1193148779e5ce7ebd0df4f2cd131f5..02fef13a303d17d717ef07df8b54c58a5302a2cc 100644 (file)
@@ -30,14 +30,15 @@ union value ;
 typedef void update_func (void *user_data,
                          const struct variable *wv, 
                          const struct variable *catvar,
-                         const struct ccase *c, void *aux);
+                         const struct ccase *c,
+                         void *aux1, void *aux2);
 
-typedef void *user_data_create_func (void);
+typedef void *user_data_create_func (void *aux1, void *aux2);
 
 struct categoricals *categoricals_create (const struct variable *const *v, size_t n_vars,
                                          const struct variable *wv, enum mv_class exclude,
                                          user_data_create_func *udf,
-                                         update_func *update, void *update_aux);
+                                         update_func *update, void *aux1, void *aux2);
 
 void categoricals_destroy (struct categoricals *);