Added variable/parameter matching and error reporting
[pspp-builds.git] / src / regression.q
index 2e54e46c31a70cdc99a751ee2b0e70f78ef843dc..56420c5335e964dd20ee7a3de9a21aa484fd6aa3 100644 (file)
 #include <gsl/gsl_matrix.h>
 #include "alloc.h"
 #include "case.h"
+#include "casefile.h"
+#include "cat.h"
+#include "command.h"
 #include "dictionary.h"
+#include "error.h"
 #include "file-handle.h"
-#include "command.h"
+#include "gettext.h"
 #include "lexer.h"
+#include <linreg/pspp_linreg.h>
 #include "tab.h"
 #include "var.h"
 #include "vfm.h"
-#include "casefile.h"
-#include <linreg/pspp_linreg.h>
-#include "cat.h"
+
 /* (headers) */
 
 
@@ -69,6 +72,11 @@ static struct cmd_regression cmd;
  */
 size_t *indep_vars;
 
+/*
+  Return value for the procedure.
+ */
+int pspp_reg_rc = CMD_SUCCESS;
+
 static void run_regression (const struct casefile *, void *);
 /* 
    STATISTICS subcommand output functions.
@@ -94,7 +102,7 @@ static void statistics_keyword_output (void (*)(pspp_linreg_cache *),
 static void
 reg_stats_r (pspp_linreg_cache * c)
 {
-  struct table *t;
+  struct tab_table *t;
   int n_rows = 2;
   int n_cols = 5;
   double rsq;
@@ -143,7 +151,8 @@ reg_stats_coeff (pspp_linreg_cache * c)
   struct tab_table *t;
 
   assert (c != NULL);
-  n_rows = 2 + c->param_estimates->size;
+  n_rows = 2;
+
   t = tab_create (n_cols, n_rows, 0);
   tab_headers (t, 2, 0, 1, 0);
   tab_dim (t, tab_natural_dimensions);
@@ -299,7 +308,45 @@ reg_stats_f (pspp_linreg_cache * c)
 static void
 reg_stats_bcov (pspp_linreg_cache * c)
 {
+  int n_cols;
+  int n_rows;
+  int i;
+  int j;
+  int k;
+  int row;
+  int col;
+  const char *label;
+  struct tab_table *t;
+
   assert (c != NULL);
+  n_cols = c->n_indeps + 1 + 2;
+  n_rows = 2 * (c->n_indeps + 1);
+  t = tab_create (n_cols, n_rows, 0);
+  tab_headers (t, 2, 0, 1, 0);
+  tab_dim (t, tab_natural_dimensions);
+  tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
+  tab_hline (t, TAL_2, 0, n_cols - 1, 1);
+  tab_vline (t, TAL_2, 2, 0, n_rows - 1);
+  tab_vline (t, TAL_0, 1, 0, 0);
+  tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Model"));
+  tab_text (t, 1, 1, TAB_CENTER | TAT_TITLE, _("Covariances"));
+  for (i = 1; i < c->n_indeps + 1; i++)
+    {
+      j = indep_vars[(i - 1)];
+      struct variable *v = cmd.v_variables[j];
+      label = var_to_string (v);
+      tab_text (t, 2, i, TAB_CENTER, label);
+      tab_text (t, i + 2, 0, TAB_CENTER, label);
+      for (k = 1; k < c->n_indeps + 1; k++)
+       {
+         col = (i <= k) ? k : i;
+         row = (i <= k) ? i : k;
+         tab_float (t, k + 2, i, TAB_CENTER,
+                    gsl_matrix_get (c->cov, row, col), 8, 3);
+       }
+    }
+  tab_title (t, 0, _("Coefficient Correlations"));
+  tab_submit (t);
 }
 static void
 reg_stats_ses (pspp_linreg_cache * c)
@@ -373,7 +420,7 @@ subcommand_statistics (int *keywords, pspp_linreg_cache * c)
        */
       for (i = 0; i < f; i++)
        {
-         *(keywords + i) = 1;
+         keywords[i] = 1;
        }
     }
   else
@@ -392,10 +439,10 @@ subcommand_statistics (int *keywords, pspp_linreg_cache * c)
        */
       if (keywords[defaults] | d)
        {
-         *(keywords + anova) = 1;
-         *(keywords + outs) = 1;
-         *(keywords + coeff) = 1;
-         *(keywords + r) = 1;
+         keywords[anova] = 1;
+         keywords[outs] = 1;
+         keywords[coeff] = 1;
+         keywords[r] = 1;
        }
     }
   statistics_keyword_output (reg_stats_r, keywords[r], c);
@@ -424,7 +471,7 @@ cmd_regression (void)
     }
   multipass_procedure_with_splits (run_regression, &cmd);
 
-  return CMD_SUCCESS;
+  return pspp_reg_rc;
 }
 
 /*
@@ -447,13 +494,14 @@ is_depvar (size_t k)
 }
 
 static void
-run_regression (const struct casefile *cf, void *cmd_)
+run_regression (const struct casefile *cf, void *cmd_ UNUSED)
 {
   size_t i;
   size_t k;
   size_t n_data = 0;
   size_t row;
   int n_indep;
+  int j = 0;
   const union value *val;
   struct casereader *r;
   struct casereader *r2;
@@ -468,11 +516,11 @@ run_regression (const struct casefile *cf, void *cmd_)
 
   n_data = casefile_get_case_cnt (cf);
   n_indep = cmd.n_variables - cmd.n_dependent;
-  indep_vars = (size_t *) malloc (n_indep * sizeof (*indep_vars));
+  indep_vars = xnmalloc (n_indep, sizeof *indep_vars);
 
   Y = gsl_vector_alloc (n_data);
   lopts.get_depvar_mean_std = 1;
-  lopts.get_indep_mean_std = (int *) malloc (n_indep * sizeof (int));
+  lopts.get_indep_mean_std = xnmalloc (n_indep, sizeof (int));
 
   lcache = pspp_linreg_cache_alloc (n_data, n_indep);
   lcache->indep_means = gsl_vector_alloc (n_indep);
@@ -522,7 +570,13 @@ run_regression (const struct casefile *cf, void *cmd_)
           */
          if (is_depvar (i))
            {
-             assert (v->type == NUMERIC);
+             if (v->type != NUMERIC)
+               {
+                 msg (SE, gettext ("Dependent variable must be numeric."));
+                 pspp_reg_rc = CMD_FAILURE;
+                 return;
+               }
+             lcache->depvar = (const struct var *) v;
              gsl_vector_set (Y, row, val->f);
            }
          else
@@ -543,6 +597,18 @@ run_regression (const struct casefile *cf, void *cmd_)
            }
        }
     }
+  /*
+     Now that we know the number of coefficients, allocate space
+     and store pointers to the variables that correspond to the
+     coefficients.
+   */
+  lcache->coeff = xnmalloc (X->m->size2 + 1, sizeof (*lcache->coeff));
+  for (i = 0; i < X->m->size2; i++)
+    {
+      j = i + 1;               /* The first coeff is the intercept. */
+      lcache->coeff[j].v =
+       (const struct variable *) design_matrix_col_to_var (X, i);
+    }
   /* 
      Find the least-squares estimates and other statistics.
    */
@@ -554,6 +620,7 @@ run_regression (const struct casefile *cf, void *cmd_)
   free (lopts.get_indep_mean_std);
   free (indep_vars);
   casereader_destroy (r);
+  return;
 }
 
 /*