X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fcrosstabs.q;h=bb4acafa62c6cd279bb7622dc4ff18206bd415e3;hb=dfd1972f7bcb550a4fc3b05dbe7e71d12334b0a7;hp=700f02c194f4ef10f5f9389a7b37d30fc5d5f4ed;hpb=e4a1db0dd8deb893e19c00cdf30d8eae58c2f00e;p=pspp diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 700f02c194..bb4acafa62 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -56,8 +56,7 @@ #include #include #include -#include -#include +#include #include "minmax.h" #include "xalloc.h" @@ -161,41 +160,6 @@ struct pivot_table double total; /* Grand total. */ }; -/* A crosstabulation of exactly 2 variables, conditional on zero - or more other variables having given values. */ -struct crosstab - { - /* Case counts. */ - double missing; - - /* Variables. */ - int n_vars; /* Number of variables (at least 2). */ - const struct variable **vars; - union value *values; /* Values of variables beyond 2. */ - - /* Data. */ - struct table_entry **entries; - size_t n_entries; - - /* Column values, number of columns. */ - union value *cols; - int n_cols; - - /* Row values, number of rows. */ - union value *rows; - int n_rows; - - /* Number of statistically interesting columns/rows - (columns/rows with data in them). */ - int ns_cols, ns_rows; - - /* Matrix contents. */ - double *mat; /* Matrix proper. */ - double *row_tot; /* Row totals. */ - double *col_tot; /* Column totals. */ - double total; /* Grand total. */ - }; - /* Integer mode variable info. */ struct var_range { @@ -212,6 +176,7 @@ get_var_range (const struct variable *v) struct crosstabs_proc { + const struct dictionary *dict; enum { INTEGER, GENERAL } mode; enum mv_class exclude; bool pivot; @@ -239,6 +204,7 @@ static void init_proc (struct crosstabs_proc *proc, struct dataset *ds) { const struct variable *wv = dict_get_weight (dataset_dict (ds)); + proc->dict = dataset_dict (ds); proc->bad_warn = true; proc->variables = NULL; proc->n_variables = 0; @@ -263,8 +229,8 @@ free_proc (struct crosstabs_proc *proc) The rest of the data was allocated and destroyed at a lower level already. */ - free (pt); } + free (proc->pivots); } static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds, @@ -276,8 +242,7 @@ static void tabulate_general_case (struct pivot_table *, const struct ccase *, static void tabulate_integer_case (struct pivot_table *, const struct ccase *, double weight); static void postcalc (struct crosstabs_proc *); -static void submit (struct crosstabs_proc *, struct pivot_table *, - struct tab_table *); +static void submit (struct pivot_table *, struct tab_table *); /* Parse and execute CROSSTABS, then clean up. */ int @@ -869,7 +834,7 @@ make_summary_table (struct crosstabs_proc *proc) struct string name; int i; - summary = tab_create (7, 3 + proc->n_pivots, 1); + summary = tab_create (7, 3 + proc->n_pivots); tab_title (summary, _("Summary.")); tab_headers (summary, 1, 0, 3, 0); tab_joint_text (summary, 1, 0, 6, 0, TAB_CENTER, _("Cases")); @@ -916,15 +881,15 @@ make_summary_table (struct crosstabs_proc *proc) { tab_double (summary, i * 2 + 1, 0, TAB_RIGHT, n[i], &proc->weight_format); - tab_text (summary, i * 2 + 2, 0, TAB_RIGHT | TAT_PRINTF, "%.1f%%", - n[i] / n[2] * 100.); + tab_text_format (summary, i * 2 + 2, 0, TAB_RIGHT, "%.1f%%", + n[i] / n[2] * 100.); } tab_next_row (summary); } ds_destroy (&name); - submit (proc, NULL, summary); + submit (NULL, summary); } /* Output. */ @@ -947,8 +912,6 @@ static void display_symmetric (struct crosstabs_proc *, struct pivot_table *, static void display_risk (struct pivot_table *, struct tab_table *); static void display_directional (struct crosstabs_proc *, struct pivot_table *, struct tab_table *); -static void crosstabs_dim (struct tab_table *, struct outp_driver *, - void *proc); static void table_value_missing (struct crosstabs_proc *proc, struct tab_table *table, int c, int r, unsigned char opt, const union value *v, @@ -1028,22 +991,22 @@ output_pivot_table (struct crosstabs_proc *proc, struct pivot_table *pt) if (chisq) { display_dimensions (proc, &x, chisq, first_difference); - display_chisq (pt, chisq, &showed_fisher); + display_chisq (&x, chisq, &showed_fisher); } if (sym) { display_dimensions (proc, &x, sym, first_difference); - display_symmetric (proc, pt, sym); + display_symmetric (proc, &x, sym); } if (risk) { display_dimensions (proc, &x, risk, first_difference); - display_risk (pt, risk); + display_risk (&x, risk); } if (direct) { display_dimensions (proc, &x, direct, first_difference); - display_directional (proc, pt, direct); + display_directional (proc, &x, direct); } /* Free the parts of x that are not owned by pt. In @@ -1056,18 +1019,18 @@ output_pivot_table (struct crosstabs_proc *proc, struct pivot_table *pt) free (x.col_tot); } - submit (proc, NULL, table); + submit (NULL, table); if (chisq) { if (!showed_fisher) tab_resize (chisq, 4 + (pt->n_vars - 2), -1); - submit (proc, pt, chisq); + submit (pt, chisq); } - submit (proc, pt, sym); - submit (proc, pt, risk); - submit (proc, pt, direct); + submit (pt, sym); + submit (pt, risk); + submit (pt, direct); free (pt->cols); } @@ -1180,8 +1143,7 @@ create_crosstab_table (struct crosstabs_proc *proc, struct pivot_table *pt) int i; table = tab_create (pt->n_consts + 1 + pt->n_cols + 1, - (pt->n_entries / pt->n_cols) * 3 / 2 * proc->n_cells + 10, - true); + (pt->n_entries / pt->n_cols) * 3 / 2 * proc->n_cells + 10); tab_headers (table, pt->n_consts + 1, 0, 2, 0); /* First header line. */ @@ -1219,14 +1181,16 @@ create_crosstab_table (struct crosstabs_proc *proc, struct pivot_table *pt) { const struct variable *var = pt->const_vars[i]; size_t ofs; + char *s = NULL; ds_put_format (&title, ", %s=", var_get_name (var)); /* Insert the formatted value of the variable, then trim leading spaces in what was just inserted. */ ofs = ds_length (&title); - data_out (&pt->const_values[i], var_get_print_format (var), - ds_put_uninit (&title, var_get_width (var))); + s = data_out (&pt->const_values[i], dict_get_encoding (proc->dict), var_get_print_format (var)); + ds_put_cstr (&title, s); + free (s); ds_remove (&title, ofs, ss_cspan (ds_substr (&title, ofs, SIZE_MAX), ss_cstr (" "))); } @@ -1255,8 +1219,7 @@ create_chisq_table (struct pivot_table *pt) struct tab_table *chisq; chisq = tab_create (6 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 3 / 2 * N_CHISQ + 10, - 1); + pt->n_entries / pt->n_cols * 3 / 2 * N_CHISQ + 10); tab_headers (chisq, 1 + (pt->n_vars - 2), 0, 1, 0); tab_title (chisq, _("Chi-square tests.")); @@ -1268,9 +1231,9 @@ create_chisq_table (struct pivot_table *pt) tab_text (chisq, 3, 0, TAB_RIGHT | TAT_TITLE, _("Asymp. Sig. (2-sided)")); tab_text (chisq, 4, 0, TAB_RIGHT | TAT_TITLE, - _("Exact. Sig. (2-sided)")); + _("Exact Sig. (2-sided)")); tab_text (chisq, 5, 0, TAB_RIGHT | TAT_TITLE, - _("Exact. Sig. (1-sided)")); + _("Exact Sig. (1-sided)")); tab_offset (chisq, 0, 1); return chisq; @@ -1283,7 +1246,7 @@ create_sym_table (struct pivot_table *pt) struct tab_table *sym; sym = tab_create (6 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 7 + 10, 1); + pt->n_entries / pt->n_cols * 7 + 10); tab_headers (sym, 2 + (pt->n_vars - 2), 0, 1, 0); tab_title (sym, _("Symmetric measures.")); @@ -1305,14 +1268,13 @@ create_risk_table (struct pivot_table *pt) { struct tab_table *risk; - risk = tab_create (4 + (pt->n_vars - 2), pt->n_entries / pt->n_cols * 4 + 10, - 1); + risk = tab_create (4 + (pt->n_vars - 2), pt->n_entries / pt->n_cols * 4 + 10); tab_headers (risk, 1 + pt->n_vars - 2, 0, 2, 0); tab_title (risk, _("Risk estimate.")); tab_offset (risk, pt->n_vars - 2, 0); - tab_joint_text (risk, 2, 0, 3, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF, - _("95%% Confidence Interval")); + tab_joint_text_format (risk, 2, 0, 3, 0, TAB_CENTER | TAT_TITLE, + _("95%% Confidence Interval")); tab_text (risk, 0, 1, TAB_LEFT | TAT_TITLE, _("Statistic")); tab_text (risk, 1, 1, TAB_RIGHT | TAT_TITLE, _("Value")); tab_text (risk, 2, 1, TAB_RIGHT | TAT_TITLE, _("Lower")); @@ -1331,7 +1293,7 @@ create_direct_table (struct pivot_table *pt) struct tab_table *direct; direct = tab_create (7 + (pt->n_vars - 2), - pt->n_entries / pt->n_cols * 7 + 10, 1); + pt->n_entries / pt->n_cols * 7 + 10); tab_headers (direct, 3 + (pt->n_vars - 2), 0, 1, 0); tab_title (direct, _("Directional measures.")); @@ -1376,8 +1338,7 @@ delete_missing (struct pivot_table *pt) /* Prepare table T for submission, and submit it. */ static void -submit (struct crosstabs_proc *proc, struct pivot_table *pt, - struct tab_table *t) +submit (struct pivot_table *pt, struct tab_table *t) { int i; @@ -1387,7 +1348,7 @@ submit (struct crosstabs_proc *proc, struct pivot_table *pt, tab_resize (t, -1, 0); if (tab_nr (t) == tab_t (t)) { - tab_destroy (t); + table_unref (&t->table); return; } tab_offset (t, 0, 0); @@ -1401,49 +1362,8 @@ submit (struct crosstabs_proc *proc, struct pivot_table *pt, tab_box (t, -1, -1, -1, TAL_GAP, 0, tab_t (t), tab_l (t) - 1, tab_nr (t) - 1); tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1); - tab_dim (t, crosstabs_dim, proc); - tab_submit (t); -} -/* Sets the widths of all the columns and heights of all the rows in - table T for driver D. */ -static void -crosstabs_dim (struct tab_table *t, struct outp_driver *d, void *proc_) -{ - struct crosstabs_proc *proc = proc_; - int i; - - /* Width of a numerical column. */ - int c = outp_string_width (d, "0.000000", OUTP_PROPORTIONAL); - if (proc->exclude == MV_NEVER) - c += outp_string_width (d, "M", OUTP_PROPORTIONAL); - - /* Set width for header columns. */ - if (t->l != 0) - { - size_t i; - int w; - - w = d->width - c * (t->nc - t->l); - for (i = 0; i <= t->nc; i++) - w -= t->wrv[i]; - w /= t->l; - - if (w < d->prop_em_width * 8) - w = d->prop_em_width * 8; - - if (w > d->prop_em_width * 15) - w = d->prop_em_width * 15; - - for (i = 0; i < t->l; i++) - t->w[i] = w; - } - - for (i = t->l; i < t->nc; i++) - t->w[i] = c; - - for (i = 0; i < t->nr; i++) - t->h[i] = tab_natural_height (t, d, i); + tab_submit (t); } static bool @@ -1544,27 +1464,21 @@ table_value_missing (struct crosstabs_proc *proc, struct tab_table *table, int c, int r, unsigned char opt, const union value *v, const struct variable *var) { - struct substring s; - const struct fmt_spec *print = var_get_print_format (var); - const char *label = var_lookup_value_label (var, v); - if (label) - { - tab_text (table, c, r, TAB_LEFT, label); - return; - } - - s.string = tab_alloc (table, print->w); - data_out (v, print, s.string); - s.length = print->w; - if (proc->exclude == MV_NEVER && var_is_num_missing (var, v->f, MV_USER)) - s.string[s.length++] = 'M'; - while (s.length && *s.string == ' ') + if (label != NULL) + tab_text (table, c, r, TAB_LEFT, label); + else { - s.length--; - s.string++; + const struct fmt_spec *print = var_get_print_format (var); + if (proc->exclude == MV_NEVER && var_is_value_missing (var, v, MV_USER)) + { + char *s = data_out (v, dict_get_encoding (proc->dict), print); + tab_text_format (table, c, r, opt, "%sM", s + strspn (s, " ")); + free (s); + } + else + tab_value (table, c, r, opt, v, proc->dict, print); } - tab_raw (table, c, r, opt, &s); } /* Draws a line across TABLE at the current row to indicate the most @@ -1589,27 +1503,26 @@ display_dimensions (struct crosstabs_proc *proc, struct pivot_table *pt, additionally suffixed with a letter `M'. */ static void format_cell_entry (struct tab_table *table, int c, int r, double value, - char suffix, bool mark_missing) + char suffix, bool mark_missing, const struct dictionary *dict) { const struct fmt_spec f = {FMT_F, 10, 1}; union value v; - struct substring s; + char suffixes[3]; + int suffix_len; + char *s; - s.length = 10; - s.string = tab_alloc (table, 16); v.f = value; - data_out (&v, &f, s.string); - while (*s.string == ' ') - { - s.length--; - s.string++; - } + s = data_out (&v, dict_get_encoding (dict), &f); + + suffix_len = 0; if (suffix != 0) - s.string[s.length++] = suffix; + suffixes[suffix_len++] = suffix; if (mark_missing) - s.string[s.length++] = 'M'; + suffixes[suffix_len++] = 'M'; + suffixes[suffix_len] = '\0'; - tab_raw (table, c, r, TAB_RIGHT, &s); + tab_text_format (table, c, r, TAB_RIGHT, "%s%s", + s + strspn (s, " "), suffixes); } /* Displays the crosstabulation table. */ @@ -1684,7 +1597,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt, default: NOT_REACHED (); } - format_cell_entry (table, c, i, v, suffix, mark_missing); + format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict); } mp++; @@ -1735,7 +1648,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt, NOT_REACHED (); } - format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing); + format_cell_entry (table, pt->n_cols, 0, v, suffix, mark_missing, proc->dict); tab_next_row (table); } } @@ -1785,7 +1698,7 @@ display_crosstabulation (struct crosstabs_proc *proc, struct pivot_table *pt, NOT_REACHED (); } - format_cell_entry (table, c, i, v, suffix, mark_missing); + format_cell_entry (table, c, i, v, suffix, mark_missing, proc->dict); } last_row = i; } @@ -1815,7 +1728,6 @@ display_chisq (struct pivot_table *pt, struct tab_table *chisq, double chisq_v[N_CHISQ]; double fisher1, fisher2; int df[N_CHISQ]; - int s = 0; int i; @@ -1828,7 +1740,6 @@ display_chisq (struct pivot_table *pt, struct tab_table *chisq, if ((i != 2 && chisq_v[i] == SYSMIS) || (i == 2 && fisher1 == SYSMIS)) continue; - s = 1; tab_text (chisq, 0, 0, TAB_LEFT, gettext (chisq_stats[i])); if (i != 2) @@ -2097,8 +2008,8 @@ display_directional (struct crosstabs_proc *proc, struct pivot_table *pt, else string = var_get_name (pt->vars[1]); - tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF, - gettext (stats_names[j][k]), string); + tab_text_format (direct, j, 0, TAB_LEFT, + gettext (stats_names[j][k]), string); } } }