doc/pspp-figures/ctables19.sps \
doc/pspp-figures/ctables20.sps \
doc/pspp-figures/ctables21.sps \
+ doc/pspp-figures/ctables22.sps \
doc/pspp-figures/crosstabs.sps \
doc/pspp-figures/descriptives.sps \
doc/pspp-figures/flip.sps \
.spv.html:
$(convert) -O format=html -O bare=true
+# Make sure that tutorial.stt outputs all layers, because a few of the
+# examples in the manual rely on that and it would be easy to replace
+# it with a style that didn't.
+ALL_LOCAL += tutorial-stt-must-print-all-layers
+tutorial-stt-must-print-all-layers:
+ $(AM_V_GEN)grep 'printAllLayers="true"' $(srcdir)/doc/tutorial.stt >/dev/null 2>&1 && touch $@
+
# Convert a text file into a Texinfo file.
.txt.texi:
$(AM_V_GEN)$(SED) -e 's/@/@@/g' $< > $@
--- /dev/null
+GET FILE='nhtsa.sav'.
+CTABLES
+ /VLABELS VARIABLES=ALL DISPLAY=NAME
+ /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLE.ID, LAYER.ID, SUBTABLE.ID]
+ /SLABELS POSITION=ROW.
This section lists the summary functions that can be applied to cells
in @code{CTABLES}. Many of these functions have an @var{area} in
-their names. The supported areas are:
-
-@itemize @bullet
-@item
-Areas that correspond to parts of @dfn{sections}, where stacked
-variables divide each section from another:
+their names, indicating that they summarize over multiple cells within
+an area of the output chosen by the user. The following basic
+@var{area}s are supported, in decreasing order of size:
@table @code
@item TABLE
-An entire section.
+A @dfn{section}. Stacked variables divide sections of the output from
+each other. sections may span multiple layers.
@item LAYER
-A layer within a section.
-
-@item LAYERROW
-A row in one layer within a section.
+A section within a single layer.
-@item LAYERCOL
-A column in one layer within a section.
+@item SUBTABLE
+A @dfn{subtable}, whose contents are the cells that pair an innermost
+row variable and an innermost column variable within a single layer.
@end table
-@item
-Areas that correspond to parts of @dfn{subtables}, whose contents are
-the cells that pair an innermost row variable and an innermost column
-variable within a single layer. A section can contain multiple
-subtables and a subtable is always within a single section:
+The following shows how the output for the table expression @code{qn61
+> qn57 BY qnd7a > qn86 + qn64b BY qns3a}@footnote{This is not
+necessarily a meaningful table, so for clarity variable labels are
+omitted.} is divided up into @code{TABLE}, @code{LAYER}, and
+@code{SUBTABLE} areas. Each unique value for Table ID is one section,
+and similarly for Layer ID and Subtable ID. Thus, this output has two
+@code{TABLE} areas (one for @code{qnd7a} and one for @code{qn64b}),
+four @code{LAYER} areas (for those two variables, per layer), and 12
+@code{SUBTABLE} areas.
+@psppoutput {ctables22}
-@table @code
-@item ROW
-A row within a subtable.
+@code{CTABLES} also supports the following @var{area}s that further
+divide a subtable or a layer within a section:
-@item COL
-A column within a subtable.
+@table @code
+@item LAYERROW
+@itemx LAYERCOL
+A row or column, respectively, in one layer of a section.
-@item SUBTABLE
-All the cells in a subtable.
+@item ROW
+@itemx ROW
+A row or column, respectively, in a subtable.
@end table
-@end itemize
-
The following summary functions may be applied to any variable
regardless of whether it is categorical or scalar. The default label
for each function is listed in parentheses:
<horizontalCategoryBorderColumns borderStyleType="solid" color="#000000"/>
<verticalCategoryBorderColumns borderStyleType="solid" color="#000000"/>
</borderProperties>
- <printingProperties printAllLayers="false" rescaleLongTableToFitPage="false" rescaleWideTableToFitPage="false" windowOrphanLines="0"/>
+ <printingProperties printAllLayers="true" rescaleLongTableToFitPage="false" rescaleWideTableToFitPage="false" windowOrphanLines="0"/>
</tableProperties>
const struct ctables_cell *example;
- int sequence;
+ size_t sequence;
double d_valid; /* Dictionary weight. */
double d_count;
double d_total;
return 0;
}
+static int
+ctables_cell_compare_leaf_3way (const void *a_, const void *b_,
+ const void *aux UNUSED)
+{
+ struct ctables_cell *const *ap = a_;
+ struct ctables_cell *const *bp = b_;
+ const struct ctables_cell *a = *ap;
+ const struct ctables_cell *b = *bp;
+
+ for (enum pivot_axis_type axis = 0; axis < PIVOT_N_AXES; axis++)
+ {
+ int al = a->axes[axis].leaf;
+ int bl = b->axes[axis].leaf;
+ if (al != bl)
+ return al > bl ? 1 : -1;
+ }
+ return 0;
+}
+
/* Algorithm:
For each row:
{
struct ctables_section *s = &t->sections[j];
sections[n_sections++] = s;
- n_total_cells += s->cells.count;
+ n_total_cells += hmap_count (&s->cells);
size_t depth = s->nests[a]->n;
max_depth = MAX (depth, max_depth);
struct ctables_cell_sort_aux aux = { .nest = nest, .a = a };
sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_3way, &aux);
+#if 0
+ if (a == PIVOT_AXIS_ROW)
+ {
+ size_t ids[N_CTDTS];
+ memset (ids, 0, sizeof ids);
+ for (size_t j = 0; j < n_sorted; j++)
+ {
+ struct ctables_cell *cell = sorted[j];
+ for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
+ {
+ struct ctables_domain *domain = cell->domains[dt];
+ if (!domain->sequence)
+ domain->sequence = ++ids[dt];
+ }
+ }
+ }
+#endif
+
#if 0
for (size_t j = 0; j < n_sorted; j++)
{
struct ctables_cell *cell = sorted[j];
struct ctables_cell *prev = j > 0 ? sorted[j - 1] : NULL;
- struct ctables_domain *domain = cell->domains[CTDT_SUBTABLE];
- if (!domain->sequence)
- {
- static int x;
- domain->sequence = ++x;
- }
- domain = cell->domains[CTDT_TABLE];
- if (!domain->sequence)
- {
- static int x;
- domain->sequence = ++x;
- }
-
size_t n_common = 0;
if (j > 0)
{
}
}
+ {
+ size_t n_total_cells = 0;
+ for (size_t j = 0; j < t->n_sections; j++)
+ n_total_cells += hmap_count (&t->sections[j].cells);
+
+ struct ctables_cell **sorted = xnmalloc (n_total_cells, sizeof *sorted);
+ size_t n_sorted = 0;
+ for (size_t j = 0; j < t->n_sections; j++)
+ {
+ const struct ctables_section *s = &t->sections[j];
+ struct ctables_cell *cell;
+ HMAP_FOR_EACH (cell, struct ctables_cell, node, &s->cells)
+ if (!cell->hide)
+ sorted[n_sorted++] = cell;
+ }
+ assert (n_sorted <= n_total_cells);
+ sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_leaf_3way,
+ NULL);
+ size_t ids[N_CTDTS];
+ memset (ids, 0, sizeof ids);
+ for (size_t j = 0; j < n_sorted; j++)
+ {
+ struct ctables_cell *cell = sorted[j];
+ for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
+ {
+ struct ctables_domain *domain = cell->domains[dt];
+ if (!domain->sequence)
+ domain->sequence = ++ids[dt];
+ }
+ }
+
+ free (sorted);
+ }
+
for (size_t i = 0; i < t->n_sections; i++)
{
struct ctables_section *s = &t->sections[i];
S(CTSF_ULAYERCOLPCT_SUM, "ULAYERCOLPCT.SUM", N_("Unweighted Layer Column Sum %"), CTF_PERCENT, CTFA_SCALE)
/* Debugging and troubleshooting. */
-S(CTSF_ROW_ID, "ROW.ID", N_("Row ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_COL_ID, "COL.ID", N_("Column ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_TABLE_ID, "TABLE.ID", N_("Table ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_SUBTABLE_ID, "SUBTABLE.ID", N_("Subtable ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_LAYER_ID, "LAYER.ID", N_("Layer ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_LAYERROW_ID, "LAYERROW.ID", N_("Layer Row ID"), CTF_GENERAL, CTFA_ALL)
-S(CTSF_LAYERCOL_ID, "LAYERCOL.ID", N_("Layer Column ID"), CTF_GENERAL, CTFA_ALL)
+S(CTSF_ROW_ID, "ROW.ID", N_("Row ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_COL_ID, "COL.ID", N_("Column ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_TABLE_ID, "TABLE.ID", N_("Table ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_SUBTABLE_ID, "SUBTABLE.ID", N_("Subtable ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_LAYER_ID, "LAYER.ID", N_("Layer ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_LAYERROW_ID, "LAYERROW.ID", N_("Layer Row ID"), CTF_COUNT, CTFA_ALL)
+S(CTSF_LAYERCOL_ID, "LAYERCOL.ID", N_("Layer Column ID"), CTF_COUNT, CTFA_ALL)
#if 0 /* Multiple response sets not yet implemented. */
S(CTSF_RESPONSES, "RESPONSES", N_("Responses"), CTF_COUNT, CTFA_MRSETS)
])
AT_CLEANUP
+AT_SETUP([CTABLES area definitions])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+CTABLES
+ /VLABELS VARIABLES=ALL DISPLAY=NAME
+ /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[TABLE.ID, LAYER.ID, SUBTABLE.ID]
+ /SLABELS POSITION=ROW
+ /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[ROW.ID, LAYERROW.ID]
+ /SLABELS POSITION=ROW
+ /TABLE qn61 > qn57 BY qnd7a > qn86 + qn64b BY qns3a[COL.ID, LAYERCOL.ID]
+ /SLABELS POSITION=ROW.
+]])
+AT_CHECK([pspp ctables.sps --table-look="$builddir"/all-layers.stt -O box=unicode -O width=80], [0], [dnl
+ Custom Tables
+Male
+╭─────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├─────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Subtable ID│ 1│ 1│ 2│ 2│ 3│ 3│
+│ ╶───────────────┼───┼──┼───┼──┼───┼──┤
+│ No Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Subtable ID│ 1│ 1│ 2│ 2│ 3│ 3│
+│ ╶────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Subtable ID│ 4│ 4│ 5│ 5│ 6│ 6│
+│ ╶───────────────┼───┼──┼───┼──┼───┼──┤
+│ No Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Subtable ID│ 4│ 4│ 5│ 5│ 6│ 6│
+╰─────────────────────────────┴───┴──┴───┴──┴───┴──╯
+
+ Custom Tables
+Female
+╭─────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├─────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 3│ 3│ 3│ 3│ 4│ 4│
+│ Subtable ID│ 7│ 7│ 8│ 8│ 9│ 9│
+│ ╶───────────────┼───┼──┼───┼──┼───┼──┤
+│ No Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 3│ 3│ 3│ 3│ 4│ 4│
+│ Subtable ID│ 7│ 7│ 8│ 8│ 9│ 9│
+│ ╶────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 3│ 3│ 3│ 3│ 4│ 4│
+│ Subtable ID│ 10│10│ 11│11│ 12│12│
+│ ╶───────────────┼───┼──┼───┼──┼───┼──┤
+│ No Table ID │ 1│ 1│ 1│ 1│ 2│ 2│
+│ Layer ID │ 3│ 3│ 3│ 3│ 4│ 4│
+│ Subtable ID│ 10│10│ 11│11│ 12│12│
+╰─────────────────────────────┴───┴──┴───┴──┴───┴──╯
+
+ Custom Tables
+Male
+╭──────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├──────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Row ID │ 1│ 1│ 2│ 2│ 3│ 3│
+│ Layer Row ID│ 1│ 1│ 1│ 1│ 2│ 2│
+│ ╶────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Row ID │ 4│ 4│ 5│ 5│ 6│ 6│
+│ Layer Row ID│ 3│ 3│ 3│ 3│ 4│ 4│
+│ ╶─────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Row ID │ 7│ 7│ 8│ 8│ 9│ 9│
+│ Layer Row ID│ 5│ 5│ 5│ 5│ 6│ 6│
+│ ╶────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Row ID │ 10│10│ 11│11│ 12│12│
+│ Layer Row ID│ 7│ 7│ 7│ 7│ 8│ 8│
+╰──────────────────────────────┴───┴──┴───┴──┴───┴──╯
+
+ Custom Tables
+Female
+╭──────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├──────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Row ID │ 13│13│ 14│14│ 15│15│
+│ Layer Row ID│ 9│ 9│ 9│ 9│ 10│10│
+│ ╶────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Row ID │ 16│16│ 17│17│ 18│18│
+│ Layer Row ID│ 11│11│ 11│11│ 12│12│
+│ ╶─────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Row ID │ 19│19│ 20│20│ 21│21│
+│ Layer Row ID│ 13│13│ 13│13│ 14│14│
+│ ╶────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Row ID │ 22│22│ 23│23│ 24│24│
+│ Layer Row ID│ 15│15│ 15│15│ 16│16│
+╰──────────────────────────────┴───┴──┴───┴──┴───┴──╯
+
+ Custom Tables
+Male
+╭─────────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├─────────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Column ID │ 1│ 2│ 3│ 4│ 5│ 6│
+│ Layer Column ID│ 1│ 2│ 3│ 4│ 5│ 6│
+│ ╶───────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Column ID │ 1│ 2│ 3│ 4│ 5│ 6│
+│ Layer Column ID│ 1│ 2│ 3│ 4│ 5│ 6│
+│ ╶────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Column ID │ 7│ 8│ 9│10│ 11│12│
+│ Layer Column ID│ 1│ 2│ 3│ 4│ 5│ 6│
+│ ╶───────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Column ID │ 7│ 8│ 9│10│ 11│12│
+│ Layer Column ID│ 1│ 2│ 3│ 4│ 5│ 6│
+╰─────────────────────────────────┴───┴──┴───┴──┴───┴──╯
+
+ Custom Tables
+Female
+╭─────────────────────────────────┬─────────────┬──────╮
+│ │ QND7A │ QN64B│
+│ ├──────┬──────┼───┬──┤
+│ │ Yes │ No │ │ │
+│ ├──────┼──────┤ │ │
+│ │ QN86 │ QN86 │ │ │
+│ ├───┬──┼───┬──┤ │ │
+│ │Yes│No│Yes│No│Yes│No│
+├─────────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│QN61 Yes QN57 Yes Column ID │ 13│14│ 15│16│ 17│18│
+│ Layer Column ID│ 7│ 8│ 9│10│ 11│12│
+│ ╶───────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Column ID │ 13│14│ 15│16│ 17│18│
+│ Layer Column ID│ 7│ 8│ 9│10│ 11│12│
+│ ╶────────────────────────────┼───┼──┼───┼──┼───┼──┤
+│ No QN57 Yes Column ID │ 19│20│ 21│22│ 23│24│
+│ Layer Column ID│ 7│ 8│ 9│10│ 11│12│
+│ ╶───────────────────┼───┼──┼───┼──┼───┼──┤
+│ No Column ID │ 19│20│ 21│22│ 23│24│
+│ Layer Column ID│ 7│ 8│ 9│10│ 11│12│
+╰─────────────────────────────────┴───┴──┴───┴──┴───┴──╯
+])
+AT_CLEANUP
+
AT_SETUP([CTABLES summary functions])
AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
AT_DATA([ctables.sps],
]])
AT_CHECK([pspp ctables.sps --table-look="$builddir"/all-layers.stt -O box=unicode -O width=120], [0], [])
AT_CLEANUP
+