@end example
@psppoutput {ctables16}
-With @t{ROWLABELS=OPPOSITE} or @t{COLLABELS=OPPOSITE}, row or column
-variable labels, respectively, move to the opposite axis. Only one
-axis's labels may be moved, and the setting affects only the innermost
-variable on the given axis. For example:
+@t{ROWLABELS=OPPOSITE} or @t{COLLABELS=OPPOSITE} move row or column
+variable category labels, respectively, to the opposite axis. The
+setting affects only the innermost variable on the given axis. For
+example:
@example
CTABLES /TABLE AgeGroup BY qns3a /CLABELS ROWLABELS=OPPOSITE.
@end example
@psppoutput {ctables17}
+@t{ROWLABELS=LAYER} or @t{COLLABELS=LAYER} move the innermost row or
+column variable category labels, respectively, to the layer axis.
+
+Only one axis's labels may be moved, whether to the opposite axis or
+to the layer axis.
+
@node CTABLES Per-Variable Category Options
@subsection Per-Variable Category Options
return NULL;
}
+static void
+ctables_value_insert (struct ctables_table *t, const union value *value,
+ int width)
+{
+ unsigned int hash = value_hash (value, width, 0);
+ struct ctables_value *clv = ctables_value_find__ (t, value, width, hash);
+ if (!clv)
+ {
+ clv = xmalloc (sizeof *clv);
+ value_clone (&clv->value, value, width);
+ hmap_insert (&t->clabels_values_map, &clv->node, hash);
+ }
+}
+
static struct ctables_value *
ctables_value_find (struct ctables_table *t,
const union value *value, int width)
const struct variable *var = clabels_nest->vars[clabels_nest->n - 1];
const union value *value = &cell->axes[t->clabels_from_axis].cvs[clabels_nest->n - 1].value;
const struct ctables_value *ctv = ctables_value_find (t, value, var_get_width (var));
- assert (ctv != NULL);
+ if (!ctv)
+ continue;
dindexes[n_dindexes++] = ctv->leaf;
}
{
const struct ctables_nest *nest = &stack->nests[i];
const struct variable *var = nest->vars[nest->n - 1];
- int width = var_get_width (var);
const union value *value = case_data (c, var);
if (var_is_numeric (var) && value->f == SYSMIS)
continue;
- if (!ctables_categories_match (t->categories [var_get_dict_index (var)],
- value, var))
- continue;
-
- unsigned int hash = value_hash (value, width, 0);
-
- struct ctables_value *clv = ctables_value_find__ (t, value, width, hash);
- if (!clv)
- {
- clv = xmalloc (sizeof *clv);
- value_clone (&clv->value, value, width);
- hmap_insert (&t->clabels_values_map, &clv->node, hash);
- }
+ if (ctables_categories_match (t->categories [var_get_dict_index (var)],
+ value, var))
+ ctables_value_insert (t, value, var_get_width (var));
}
}
static void
ctables_sort_clabels_values (struct ctables_table *t)
{
- int width = var_get_width (t->clabels_example);
+ const struct variable *v0 = t->clabels_example;
+ int width = var_get_width (v0);
+
+ struct ctables_categories *c0 = t->categories[var_get_dict_index (v0)];
+ if (c0->show_empty)
+ {
+ const struct val_labs *val_labs = var_get_value_labels (v0);
+ for (const struct val_lab *vl = val_labs_first (val_labs); vl;
+ vl = val_labs_next (val_labs, vl))
+ if (ctables_categories_match (c0, &vl->value, v0))
+ ctables_value_insert (t, &vl->value, width);
+ }
size_t n = hmap_count (&t->clabels_values_map);
t->clabels_values = xnmalloc (n, sizeof *t->clabels_values);
[PIVOT_AXIS_COLUMN] = PIVOT_AXIS_COLUMN,
[PIVOT_AXIS_LAYER] = PIVOT_AXIS_LAYER,
},
- .clabels_from_axis = PIVOT_AXIS_LAYER,
+ .clabels_from_axis = PIVOT_AXIS_LAYER,
.categories = categories,
.n_categories = n_vars,
.cilevel = 95,
╰─────────────────────────────────────────────────────────┴───────┴───────┴─────────┴───────┴────────┴──────┴──────────╯
])
AT_CLEANUP
+
+AT_SETUP([CTABLES CLABELS])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+CTABLES /TABLE AgeGroup BY qns3a /CLABELS ROWLABELS=OPPOSITE.
+CTABLES /TABLE AgeGroup BY qns3a /CLABELS COLLABELS=OPPOSITE.
+]])
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=120], [0], [dnl
+ Custom Tables
+╭───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ │ S3a. GENDER: │
+│ ├──────────────────────────────────────────────────────┬───────────────────────────────────────────────────────┤
+│ │ Male │ Female │
+│ ├─────────┬───────┬──────┬──────┬──────┬───────┬───────┼──────────┬──────┬───────┬──────┬──────┬──────┬────────┤
+│ │ 15 or │ 16 to │ 26 to│ 36 to│ 46 to│ 56 to │ 66 or │ 15 or │ 16 to│ 26 to │ 36 to│ 46 to│ 56 to│ 66 or │
+│ │ younger │ 25 │ 35 │ 45 │ 55 │ 65 │ older │ younger │ 25 │ 35 │ 45 │ 55 │ 65 │ older │
+│ ├─────────┼───────┼──────┼──────┼──────┼───────┼───────┼──────────┼──────┼───────┼──────┼──────┼──────┼────────┤
+│ │ Count │ Count │ Count│ Count│ Count│ Count │ Count │ Count │ Count│ Count │ Count│ Count│ Count│ Count │
+├───────┼─────────┼───────┼──────┼──────┼──────┼───────┼───────┼──────────┼──────┼───────┼──────┼──────┼──────┼────────┤
+│Age │ 0│ 594│ 476│ 489│ 526│ 516│ 531│ 0│ 505│ 491│ 548│ 649│ 731│ 943│
+│group │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+╰───────┴─────────┴───────┴──────┴──────┴──────┴───────┴───────┴──────────┴──────┴───────┴──────┴──────┴──────┴────────╯
+
+ Custom Tables
+╭──────────────────────────────┬────────────╮
+│ │S3a. GENDER:│
+│ ├────────────┤
+│ │ Count │
+├──────────────────────────────┼────────────┤
+│Age group 15 or younger Male │ 0│
+│ Female│ 0│
+│ ╶────────────────────┼────────────┤
+│ 16 to 25 Male │ 594│
+│ Female│ 505│
+│ ╶────────────────────┼────────────┤
+│ 26 to 35 Male │ 476│
+│ Female│ 491│
+│ ╶────────────────────┼────────────┤
+│ 36 to 45 Male │ 489│
+│ Female│ 548│
+│ ╶────────────────────┼────────────┤
+│ 46 to 55 Male │ 526│
+│ Female│ 649│
+│ ╶────────────────────┼────────────┤
+│ 56 to 65 Male │ 516│
+│ Female│ 731│
+│ ╶────────────────────┼────────────┤
+│ 66 or older Male │ 531│
+│ Female│ 943│
+╰──────────────────────────────┴────────────╯
+])
+AT_CLEANUP
\ No newline at end of file