+static void
+output_categories (const struct lr_spec *cmd, const struct lr_result *res)
+{
+ const struct fmt_spec *wfmt =
+ cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
+
+ int cumulative_df;
+ int i = 0;
+ const int heading_columns = 2;
+ const int heading_rows = 2;
+ struct tab_table *t;
+
+ int nc ;
+ int nr ;
+
+ int v;
+ int r = 0;
+
+ int max_df = 0;
+ int total_cats = 0;
+ for (i = 0; i < cmd->n_cat_predictors; ++i)
+ {
+ size_t n = categoricals_n_count (res->cats, i);
+ size_t df = categoricals_df (res->cats, i);
+ if (max_df < df)
+ max_df = df;
+ total_cats += n;
+ }
+
+ nc = heading_columns + 1 + max_df;
+ nr = heading_rows + total_cats;
+
+ t = tab_create (nc, nr);
+ tab_title (t, _("Categorical Variables' Codings"));
+
+ tab_headers (t, heading_columns, 0, heading_rows, 0);
+
+ tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, nc - 1, nr - 1);
+
+ tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
+ tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
+
+
+ tab_text (t, heading_columns, 1, TAB_CENTER | TAT_TITLE, _("Frequency"));
+
+ tab_joint_text_format (t, heading_columns + 1, 0, nc - 1, 0,
+ TAB_CENTER | TAT_TITLE, _("Parameter coding"));
+
+
+ for (i = 0; i < max_df; ++i)
+ {
+ int c = heading_columns + 1 + i;
+ tab_text_format (t, c, 1, TAB_CENTER | TAT_TITLE, _("(%d)"), i + 1);
+ }
+
+ cumulative_df = 0;
+ for (v = 0; v < cmd->n_cat_predictors; ++v)
+ {
+ int cat;
+ const struct interaction *cat_predictors = cmd->cat_predictors[v];
+ int df = categoricals_df (res->cats, v);
+ struct string str;
+ ds_init_empty (&str);
+
+ interaction_to_string (cat_predictors, &str);
+
+ tab_text (t, 0, heading_rows + r, TAB_LEFT | TAT_TITLE, ds_cstr (&str) );
+
+ ds_destroy (&str);
+
+ for (cat = 0; cat < categoricals_n_count (res->cats, v) ; ++cat)
+ {
+ struct string str;
+ const struct ccase *c = categoricals_get_case_by_category_real (res->cats, v, cat);
+ const double *freq = categoricals_get_user_data_by_category_real (res->cats, v, cat);
+
+ int x;
+ ds_init_empty (&str);
+
+ for (x = 0; x < cat_predictors->n_vars; ++x)
+ {
+ const union value *val = case_data (c, cat_predictors->vars[x]);
+ var_append_value_name (cat_predictors->vars[x], val, &str);
+
+ if (x < cat_predictors->n_vars - 1)
+ ds_put_cstr (&str, " ");
+ }
+
+ tab_text (t, 1, heading_rows + r, 0, ds_cstr (&str));
+ ds_destroy (&str);
+ tab_double (t, 2, heading_rows + r, 0, *freq, wfmt);
+
+ for (x = 0; x < df; ++x)
+ {
+ tab_double (t, heading_columns + 1 + x, heading_rows + r, 0, (cat == x), &F_8_0);
+ }
+ ++r;
+ }
+ cumulative_df += df;
+ }
+
+ tab_submit (t);
+
+}
+
+
+static void
+output_classification_table (const struct lr_spec *cmd, const struct lr_result *res)
+{
+ const struct fmt_spec *wfmt =
+ cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
+
+ const int heading_columns = 3;
+ const int heading_rows = 3;
+
+ struct string sv0, sv1;
+
+ const int nc = heading_columns + 3;
+ const int nr = heading_rows + 3;
+
+ struct tab_table *t = tab_create (nc, nr);
+
+ ds_init_empty (&sv0);
+ ds_init_empty (&sv1);
+
+ tab_title (t, _("Classification Table"));
+
+ tab_headers (t, heading_columns, 0, heading_rows, 0);
+
+ tab_box (t, TAL_2, TAL_2, -1, -1, 0, 0, nc - 1, nr - 1);
+ tab_box (t, -1, -1, -1, TAL_1, heading_columns, 0, nc - 1, nr - 1);
+
+ tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
+ tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
+
+ tab_text (t, 0, heading_rows, TAB_CENTER | TAT_TITLE, _("Step 1"));
+
+
+ tab_joint_text (t, heading_columns, 0, nc - 1, 0,
+ TAB_CENTER | TAT_TITLE, _("Predicted"));
+
+ tab_joint_text (t, heading_columns, 1, heading_columns + 1, 1,
+ 0, var_to_string (cmd->dep_var) );
+
+ tab_joint_text (t, 1, 2, 2, 2,
+ TAB_LEFT | TAT_TITLE, _("Observed"));
+
+ tab_text (t, 1, 3, TAB_LEFT, var_to_string (cmd->dep_var) );
+
+
+ tab_joint_text (t, nc - 1, 1, nc - 1, 2,
+ TAB_CENTER | TAT_TITLE, _("Percentage\nCorrect"));
+
+
+ tab_joint_text (t, 1, nr - 1, 2, nr - 1,
+ TAB_LEFT | TAT_TITLE, _("Overall Percentage"));
+
+
+ tab_hline (t, TAL_1, 1, nc - 1, nr - 1);
+
+ var_append_value_name (cmd->dep_var, &res->y0, &sv0);
+ var_append_value_name (cmd->dep_var, &res->y1, &sv1);
+
+ tab_text (t, 2, heading_rows, TAB_LEFT, ds_cstr (&sv0));
+ tab_text (t, 2, heading_rows + 1, TAB_LEFT, ds_cstr (&sv1));
+
+ tab_text (t, heading_columns, 2, 0, ds_cstr (&sv0));
+ tab_text (t, heading_columns + 1, 2, 0, ds_cstr (&sv1));
+
+ ds_destroy (&sv0);
+ ds_destroy (&sv1);
+
+ tab_double (t, heading_columns, 3, 0, res->tn, wfmt);
+ tab_double (t, heading_columns + 1, 4, 0, res->tp, wfmt);
+
+ tab_double (t, heading_columns + 1, 3, 0, res->fp, wfmt);
+ tab_double (t, heading_columns, 4, 0, res->fn, wfmt);
+
+ tab_double (t, heading_columns + 2, 3, 0, 100 * res->tn / (res->tn + res->fp), 0);
+ tab_double (t, heading_columns + 2, 4, 0, 100 * res->tp / (res->tp + res->fn), 0);
+
+ tab_double (t, heading_columns + 2, 5, 0,
+ 100 * (res->tp + res->tn) / (res->tp + res->tn + res->fp + res->fn), 0);
+
+
+ tab_submit (t);
+}