Added variable/parameter matching and error reporting
[pspp-builds.git] / src / regression.q
index ba413a068069cc2d0176708fc6aa0993e2b25af5..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,34 @@ static void statistics_keyword_output (void (*)(pspp_linreg_cache *),
 static void
 reg_stats_r (pspp_linreg_cache * c)
 {
+  struct tab_table *t;
+  int n_rows = 2;
+  int n_cols = 5;
+  double rsq;
+  double adjrsq;
+  double std_error;
+
   assert (c != NULL);
+  rsq = c->ssm / c->sst;
+  adjrsq = 1.0 - (1.0 - rsq) * (c->n_obs - 1.0) / (c->n_obs - c->n_indeps);
+  std_error = sqrt ((c->n_indeps - 1.0) / (c->n_obs - 1.0));
+  t = tab_create (n_cols, n_rows, 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, 1, 0, TAB_CENTER | TAT_TITLE, _("R"));
+  tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("R Square"));
+  tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Adjusted R Square"));
+  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error of the Estimate"));
+  tab_float (t, 1, 1, TAB_RIGHT, sqrt (rsq), 10, 2);
+  tab_float (t, 2, 1, TAB_RIGHT, rsq, 10, 2);
+  tab_float (t, 3, 1, TAB_RIGHT, adjrsq, 10, 2);
+  tab_float (t, 4, 1, TAB_RIGHT, std_error, 10, 2);
+  tab_title (t, 0, _("Model Summary"));
+  tab_submit (t);
 }
 
 /*
@@ -116,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);
@@ -272,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)
@@ -346,7 +420,7 @@ subcommand_statistics (int *keywords, pspp_linreg_cache * c)
        */
       for (i = 0; i < f; i++)
        {
-         *(keywords + i) = 1;
+         keywords[i] = 1;
        }
     }
   else
@@ -365,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);
@@ -397,7 +471,7 @@ cmd_regression (void)
     }
   multipass_procedure_with_splits (run_regression, &cmd);
 
-  return CMD_SUCCESS;
+  return pspp_reg_rc;
 }
 
 /*
@@ -420,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;
@@ -441,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);
@@ -495,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
@@ -516,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.
    */
@@ -527,6 +620,7 @@ run_regression (const struct casefile *cf, void *cmd_)
   free (lopts.get_indep_mean_std);
   free (indep_vars);
   casereader_destroy (r);
+  return;
 }
 
 /*