1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2017-2018 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 #ifndef OUTPUT_PIVOT_TABLE_H
18 #define OUTPUT_PIVOT_TABLE_H 1
22 #include "data/format.h"
23 #include "data/settings.h"
24 #include "libpspp/compiler.h"
25 #include "libpspp/hmap.h"
26 #include "output/table.h"
34 Pivot tables are PSPP's primary form of output. They are analogous to the
35 pivot tables you might be familiar with from spreadsheets and databases.
36 See https://en.wikipedia.org/wiki/Pivot_table for a brief introduction to
37 the overall concept of a pivot table.
39 In PSPP, the most important internal pieces of a pivot table are:
41 - Title. Every pivot table has a title that is displayed above it. It also
42 has an optional caption (displayed below it) and corner text (displayed in
43 the upper left corner).
45 - Dimensions. A dimension consists of zero or more categories. A category
46 has a label, such as "df" or "Asymp. Sig." or 123 or a variable name. The
47 categories are the leaves of a tree whose non-leaf nodes form groups of
48 categories. The tree always has a root group whose label is the name of
51 - Axes. A table has three axes: column, row, and layer. Each dimension is
52 assigned to an axis, and each axis has zero or more dimensions. When an
53 axis has more than one dimension, they are ordered from innermost to
56 - Data. A table's data consists of zero or more cells. Each cell maps from
57 a category for each dimension to a value, which is commonly a number but
58 could also be a variable name or an arbitrary text string.
60 Creating a pivot table usually consists of the following steps:
62 1. Create the table with pivot_table_create(), passing in the title.
63 It's commonly useful to set up a few options at this point:
65 - If empty rows or columns should not be displayed, set ->omit_empty to
68 - Set the format to use for "count" values with
69 pivot_table_set_weight_var() or pivot_table_set_weight_format().
71 2. Create each dimension with pivot_dimension_create() and populate it with
72 categories and, possibly, with groups that contain the categories. This
73 call also assigns the dimension to an axis.
75 In simple cases, only a call to pivot_dimension_create() is needed.
76 Other functions such as pivot_category_create_group() can be used for
77 hierarchies of categories.
79 Sometimes it's easier to create categories in tandem with inserting data,
80 for example by adding a category for a variable just before inserting the
81 first cell for that variable. In that case, creating categories and
82 inserting data can be interleaved.
84 3. Insert data. For each cell, supply the category indexes, which are
85 assigned starting from 0 in the order in which the categories were
86 created in step 2, and the value to go in the cell. If the table has a
87 small, fixed number of dimensions, functions like, e.g.
88 pivot_table_put3() for 3 dimensions, can be used. The general function
89 pivot_table_put() works for other cases.
91 4. Output the table for user consumption. Use pivot_table_submit(). */
93 /* Pivot table display styling. */
95 /* Areas of a pivot table for styling purposes. */
100 PIVOT_AREA_FOOTER, /* Footnotes. */
101 PIVOT_AREA_CORNER, /* Top-left corner. */
102 PIVOT_AREA_COLUMN_LABELS,
103 PIVOT_AREA_ROW_LABELS,
105 PIVOT_AREA_LAYERS, /* Layer indication. */
109 const char *pivot_area_to_string (enum pivot_area);
110 const struct table_area_style *pivot_area_get_default_style (enum pivot_area);
112 /* Table borders for styling purposes. */
118 PIVOT_BORDER_OUTER_LEFT,
119 PIVOT_BORDER_OUTER_TOP,
120 PIVOT_BORDER_OUTER_RIGHT,
121 PIVOT_BORDER_OUTER_BOTTOM,
124 PIVOT_BORDER_INNER_LEFT,
125 PIVOT_BORDER_INNER_TOP,
126 PIVOT_BORDER_INNER_RIGHT,
127 PIVOT_BORDER_INNER_BOTTOM,
130 PIVOT_BORDER_DATA_LEFT,
131 PIVOT_BORDER_DATA_TOP,
134 PIVOT_BORDER_DIM_ROW_HORZ,
135 PIVOT_BORDER_DIM_ROW_VERT,
136 PIVOT_BORDER_DIM_COL_HORZ,
137 PIVOT_BORDER_DIM_COL_VERT,
140 PIVOT_BORDER_CAT_ROW_HORZ,
141 PIVOT_BORDER_CAT_ROW_VERT,
142 PIVOT_BORDER_CAT_COL_HORZ,
143 PIVOT_BORDER_CAT_COL_VERT,
148 const char *pivot_border_to_string (enum pivot_border);
149 void pivot_border_get_default_style (enum pivot_border,
150 struct table_border_style *);
152 /* Sizing for rows or columns of a rendered table. The comments below talk
153 about columns and their widths but they apply equally to rows and their
155 struct pivot_table_sizing
157 /* Specific column widths, in 1/96" units. */
161 /* Specific page breaks: 0-based columns after which a page break must
162 occur, e.g. a value of 1 requests a break after the second column. */
166 /* Keeps: columns to keep together on a page if possible. */
167 struct pivot_keep *keeps;
171 void pivot_table_sizing_uninit (struct pivot_table_sizing *);
173 /* A set of columns to keep together on a page if possible, e.g. ofs=1, n=10
174 requests keeping together the 2nd through 11th columns. */
177 size_t ofs; /* 0-based first column. */
178 size_t n; /* Number of columns. */
192 const char *pivot_axis_type_to_string (enum pivot_axis_type);
194 /* An axis within a pivot table. */
197 /* dimensions[0] is the innermost dimension,
198 dimensions[1] is the next outer dimension,
200 dimensions[n_dimensions - 1] is the outermost dimension. */
201 struct pivot_dimension **dimensions;
204 /* The number of rows or columns along the axis,
205 that is, the product of dimension[*]->n_leaves.
206 It is 0 if any dimension has 0 leaves. */
209 /* Sum of dimensions[*]->label_depth. */
213 /* Successively assigns to INDEXES (which should be a "size_t *") each of the
214 combinations of the categories in AXIS's dimensions, in lexicographic order
215 with the innermost dimension iterating most quickly.
217 The value assigned to INDEXES is dynamically allocated. If the client
218 breaks out of the loop prematurely, it needs to free it with free(). */
219 #define PIVOT_AXIS_FOR_EACH(INDEXES, AXIS) \
220 for ((INDEXES) = NULL; \
221 ((INDEXES) = pivot_axis_iterator_next (INDEXES, AXIS)) != NULL;)
222 size_t *pivot_axis_iterator_next (size_t *indexes, const struct pivot_axis *);
226 A pivot_dimension identifies the categories associated with a single
227 dimension within a multidimensional pivot table.
229 A dimension contains a collection of categories, which are the leaves in a
232 (A dimension or a group can contain zero categories, but this is unusual.
233 If a dimension contains no categories, then its table cannot contain any
236 struct pivot_dimension
238 /* table->axes[axis_type]->dimensions[level] == dimension. */
239 struct pivot_table *table;
240 enum pivot_axis_type axis_type;
241 size_t level; /* 0 for innermost dimension within axis. */
243 /* table->dimensions[top_index] == dimension. */
246 /* Hierarchy of categories within the dimension. The groups and categories
247 are sorted in the order that should be used for display. This might be
248 different from the original order produced for output if the user
251 The root must always be a group, although it is allowed to have no
253 struct pivot_category *root;
255 /* All of the leaves reachable via the root.
257 The indexing for presentation_leaves is presentation order, thus
258 presentation_leaves[i]->presentation_index == i. This order is the same
259 as would be produced by an in-order traversal of the groups. It is the
260 order into which the user reordered or sorted the categories.
262 The indexing for data_leaves is that used for idx[] in struct
263 pivot_cell, thus data_leaves[i]->data_index == i. This might differ
264 from what an in-order traversal of 'root' would yield, if the user
265 reordered categories. */
266 struct pivot_category **data_leaves;
267 struct pivot_category **presentation_leaves;
268 size_t n_leaves, allocated_leaves;
271 bool hide_all_labels;
273 /* Number of rows or columns needed to express the labels. */
277 struct pivot_dimension *pivot_dimension_create (
278 struct pivot_table *, enum pivot_axis_type, const char *name, ...)
280 #define pivot_dimension_create(...) \
281 pivot_dimension_create(__VA_ARGS__, NULL_SENTINEL)
282 struct pivot_dimension *pivot_dimension_create__ (struct pivot_table *,
283 enum pivot_axis_type,
284 struct pivot_value *name);
286 void pivot_dimension_destroy (struct pivot_dimension *);
288 void pivot_dimension_dump (const struct pivot_dimension *, int indentation);
290 /* A pivot_category is a leaf (a category) or a group:
292 - For a leaf, neither index is SIZE_MAX.
294 - For a group, both indexes are SIZE_MAX.
296 Do not use 'subs' or 'n_subs' to determine whether a category is a group,
297 because a group may (pathologically) have no leaves. */
298 struct pivot_category
300 struct pivot_value *name;
301 struct pivot_category *parent;
302 struct pivot_dimension *dimension;
303 size_t label_depth, extra_depth;
307 If show_label is true, then the group itself has a row (or a column)
308 giving the group's name. Otherwise, the group's own name is not
310 struct pivot_category **subs; /* Child categories or groups. */
311 size_t n_subs, allocated_subs;
312 bool show_label; /* Display a label for the group itself? */
313 bool show_label_in_corner;
316 struct fmt_spec format;
317 size_t group_index; /* In ->parent->subs[]. */
318 size_t data_index; /* In ->dimension->data_leaves[]. */
319 size_t presentation_index; /* In ->dimension->presentation_leaves[]. */
323 pivot_category_is_group (const struct pivot_category *category)
325 return category->data_index == SIZE_MAX;
329 pivot_category_is_leaf (const struct pivot_category *category)
331 return !pivot_category_is_group (category);
334 /* Creating leaf categories. */
335 int pivot_category_create_leaves (struct pivot_category *parent, ...)
337 #define pivot_category_create_leaves(...) \
338 pivot_category_create_leaves(__VA_ARGS__, NULL_SENTINEL)
340 int pivot_category_create_leaf (
341 struct pivot_category *parent, struct pivot_value *name);
342 int pivot_category_create_leaf_rc (
343 struct pivot_category *parent, struct pivot_value *name, const char *rc);
345 /* Creating category groups. */
346 struct pivot_category *pivot_category_create_group (
347 struct pivot_category *parent, const char *name, ...) SENTINEL (0);
348 #define pivot_category_create_group(...) \
349 pivot_category_create_group(__VA_ARGS__, NULL_SENTINEL)
350 struct pivot_category *pivot_category_create_group__ (
351 struct pivot_category *parent, struct pivot_value *name);
353 void pivot_category_destroy (struct pivot_category *);
355 /* Pivot result classes.
357 These are used to mark leaf categories as having particular types of data,
358 to set their numeric formats. The formats that actually get used for these
359 classes are in the result_classes[] global array in pivot-table.c, except
360 that PIVOT_RC_OTHER comes from settings_get_format() and PIVOT_RC_COUNT
361 should come from the weight variable in the dataset's dictionary. */
362 #define PIVOT_RC_OTHER ("RC_OTHER")
363 #define PIVOT_RC_INTEGER ("RC_INTEGER")
364 #define PIVOT_RC_CORRELATION ("RC_CORRELATIONS")
365 #define PIVOT_RC_SIGNIFICANCE ("RC_SIGNIFICANCE")
366 #define PIVOT_RC_PERCENT ("RC_PERCENT")
367 #define PIVOT_RC_RESIDUAL ("RC_RESIDUAL")
368 #define PIVOT_RC_COUNT ("RC_COUNT")
370 bool pivot_result_class_change (const char *, const struct fmt_spec *);
372 /* Styling for a pivot table.
374 The division between this and the style information in struct pivot_table
375 seems fairly arbitrary. The ultimate reason for the division is simply
376 because that's how SPSS documentation and file formats do it. */
377 struct pivot_table_look
379 char *name; /* May be null. */
381 /* General properties. */
383 bool row_labels_in_corner;
384 int width_ranges[TABLE_N_AXES][2]; /* In 1/96" units. */
386 /* Footnote display settings. */
387 bool show_numeric_markers;
388 bool footnote_marker_superscripts;
391 struct table_area_style areas[PIVOT_N_AREAS];
392 struct table_border_style borders[PIVOT_N_BORDERS];
394 /* Print settings. */
395 bool print_all_layers;
396 bool paginate_layers;
397 bool shrink_to_fit[TABLE_N_AXES];
398 bool top_continuation, bottom_continuation;
400 size_t n_orphan_lines;
403 void pivot_table_look_init (struct pivot_table_look *);
404 void pivot_table_look_uninit (struct pivot_table_look *);
405 void pivot_table_look_copy (struct pivot_table_look *,
406 const struct pivot_table_look *);
408 /* A pivot table. See the top of this file for more information. */
411 /* Reference count. A pivot_table may be shared between multiple owners,
412 indicated by a reference count greater than 1. When this is the case,
413 the pivot_table must not be modified. */
417 struct pivot_table_look look;
419 /* Display settings. */
420 bool rotate_inner_column_labels;
421 bool rotate_outer_row_labels;
422 bool show_grid_lines;
424 size_t *current_layer; /* axis[PIVOT_AXIS_LAYER].n_dimensions elements. */
425 enum settings_value_show show_values;
426 enum settings_value_show show_variables;
427 struct fmt_spec weight_format;
429 /* Column and row sizing and page breaks.
430 sizing[TABLE_HORZ] is for columns, sizing[TABLE_VERT] is for rows. */
431 struct pivot_table_sizing sizing[TABLE_N_AXES];
433 /* Format settings. */
435 char decimal; /* Usually ',' or '.'. */
436 char grouping; /* Usually '.' or ','. */
437 char *ccs[5]; /* Custom currency. */
440 /* Command information. */
441 char *command_local; /* May be NULL. */
442 char *command_c; /* May be NULL. */
443 char *language; /* May be NULL. */
444 char *locale; /* May be NULL. */
446 /* Source information. */
447 char *dataset; /* May be NULL. */
448 char *datafile; /* May be NULL. */
449 time_t date; /* May be 0 if unknown. */
452 struct pivot_footnote **footnotes;
453 size_t n_footnotes, allocated_footnotes;
456 struct pivot_value *title;
457 struct pivot_value *subtype; /* Same as spv_item's subtype. */
458 struct pivot_value *corner_text;
459 struct pivot_value *caption;
463 struct pivot_dimension **dimensions;
466 /* Allocation of dimensions to rows, columns, and layers. */
467 struct pivot_axis axes[PIVOT_N_AXES];
469 struct hmap cells; /* Contains "struct pivot_cell"s. */
472 /* Creating and destroy pivot tables. */
473 struct pivot_table *pivot_table_create (const char *title);
474 struct pivot_table *pivot_table_create__ (struct pivot_value *title,
475 const char *subtype);
476 struct pivot_table *pivot_table_create_for_text (struct pivot_value *title,
477 struct pivot_value *content);
479 struct pivot_table *pivot_table_ref (const struct pivot_table *);
480 void pivot_table_unref (struct pivot_table *);
481 bool pivot_table_is_shared (const struct pivot_table *);
484 const struct pivot_table_look *pivot_table_get_look (
485 const struct pivot_table *);
486 void pivot_table_set_look (struct pivot_table *,
487 const struct pivot_table_look *);
489 /* Format of PIVOT_RC_COUNT cells. */
490 void pivot_table_set_weight_var (struct pivot_table *,
491 const struct variable *);
492 void pivot_table_set_weight_format (struct pivot_table *,
493 const struct fmt_spec *);
496 bool pivot_table_is_empty (const struct pivot_table *);
499 void pivot_table_submit (struct pivot_table *);
502 void pivot_table_put (struct pivot_table *, const size_t *dindexes, size_t n,
503 struct pivot_value *);
504 void pivot_table_put1 (struct pivot_table *, size_t idx1,
505 struct pivot_value *);
506 void pivot_table_put2 (struct pivot_table *, size_t idx1, size_t idx2,
507 struct pivot_value *);
508 void pivot_table_put3 (struct pivot_table *, size_t idx1, size_t idx2,
509 size_t idx3, struct pivot_value *);
510 void pivot_table_put4 (struct pivot_table *, size_t idx1, size_t idx2,
511 size_t idx3, size_t idx4, struct pivot_value *);
513 const struct pivot_value *pivot_table_get (const struct pivot_table *,
514 const size_t *dindexes);
516 struct pivot_value *pivot_table_get_rw (struct pivot_table *,
517 const size_t *dindexes);
521 Use pivot_table_create_footnote() to create a footnote.
522 Use pivot_value_add_footnote() to add a reference to a footnote. */
523 struct pivot_footnote
526 struct pivot_value *content;
527 struct pivot_value *marker;
531 struct pivot_footnote *pivot_table_create_footnote (
532 struct pivot_table *, struct pivot_value *content);
533 struct pivot_footnote *pivot_table_create_footnote__ (
534 struct pivot_table *, size_t idx,
535 struct pivot_value *marker, struct pivot_value *content);
537 void pivot_footnote_destroy (struct pivot_footnote *);
540 void pivot_table_convert_indexes_ptod (const struct pivot_table *,
541 const size_t *pindexes[PIVOT_N_AXES],
543 size_t *pivot_table_enumerate_axis (const struct pivot_table *,
544 enum pivot_axis_type,
545 const size_t *layer_indexes,
546 bool omit_empty, size_t *n);
547 #define PIVOT_ENUMERATION_FOR_EACH(INDEXES, ENUMERATION, AXIS) \
548 for ((INDEXES) = (ENUMERATION); *(INDEXES) != SIZE_MAX; \
549 (INDEXES) += MAX (1, (AXIS)->n_dimensions))
551 void pivot_table_assign_label_depth (struct pivot_table *);
553 void pivot_table_dump (const struct pivot_table *, int indentation);
557 enum pivot_value_type
559 PIVOT_VALUE_NUMERIC, /* A value of a numeric variable. */
560 PIVOT_VALUE_STRING, /* A value of a string variable. */
561 PIVOT_VALUE_VARIABLE, /* Name of a variable. */
562 PIVOT_VALUE_TEXT, /* Text. */
563 PIVOT_VALUE_TEMPLATE, /* Templated text. */
566 /* A pivot_value is the content of a single pivot table cell. A pivot_value is
567 also a pivot table's title, caption, footnote marker and contents, and so
570 A given pivot_value is one of:
572 1. A number resulting from a calculation (PIVOT_VALUE_NUMERIC). Use
573 pivot_value_new_number() to create such a pivot_value.
575 A numeric pivot_value has an associated display format (usually an F or
576 PCT format). This format can be set directly on the pivot_value, but
577 that is not usually the easiest way. Instead, it is usually true that
578 all of the values in a single category should have the same format
579 (e.g. all "Significance" values might use format F40.3), so PSPP makes
580 it easy to set the default format for a category while creating the
581 category. See pivot_dimension_create() for more details.
583 For numbers that should be displayed as integers,
584 pivot_value_new_integer() can occasionally be a useful special case.
586 2. A numeric or string value obtained from data (PIVOT_VALUE_NUMERIC or
587 PIVOT_VALUE_STRING). If such a value corresponds to a variable, then the
588 variable's name can be attached to the pivot_value. If the value has a
589 value label, then that can also be attached. When a label is present,
590 the user can control whether to show the value or the label or both.
592 Use pivot_value_new_var_value() to create pivot_values of these kinds.
594 3. A variable name (PIVOT_VALUE_VARIABLE). The variable label, if any, can
595 be attached too, and again the user can control whether to show the value
596 or the label or both.
598 4. A text string (PIVOT_VALUE_TEXT). The value stores the string in English
599 and translated into the output language (localized). Use
600 pivot_value_new_text() or pivot_value_new_text_format() for those cases.
601 In some cases, only an English or a localized version is available for
602 one reason or another, although this is regrettable; in those cases, use
603 pivot_value_new_user_text() or pivot_value_new_user_text_nocopy().
605 (There is also a PIVOT_VALUE_TEMPLATE but PSPP does not yet create these
612 A pivot_value may reference any number of footnotes. Use
613 pivot_value_add_footnote() to add a footnote reference. The footnotes being
614 referenced must first be created with pivot_table_create_footnote().
620 A pivot_value can have specific font and cell styles. Only the user should
625 struct font_style *font_style;
626 struct cell_style *cell_style;
633 const struct pivot_footnote **footnotes;
636 enum pivot_value_type type;
639 /* PIVOT_VALUE_NUMERIC. */
642 double x; /* The numeric value. */
643 struct fmt_spec format; /* Format to display 'x'. */
644 char *var_name; /* May be NULL. */
645 char *value_label; /* May be NULL. */
646 enum settings_value_show show; /* Show value or label or both? */
650 /* PIVOT_VALUE_STRING. */
653 char *s; /* The string value. */
654 bool hex; /* Display in hex? */
655 char *var_name; /* May be NULL. */
656 char *value_label; /* May be NULL. */
657 enum settings_value_show show; /* Show value or label or both? */
661 /* PIVOT_VALUE_VARIABLE. */
665 char *var_label; /* May be NULL. */
666 enum settings_value_show show; /* Show name or label or both? */
670 /* PIVOT_VALUE_TEXT. */
673 char *local; /* Localized. */
674 char *c; /* English. */
675 char *id; /* Identifier. */
680 /* PIVOT_VALUE_TEMPLATE. */
683 char *local; /* Localized. */
684 char *id; /* Identifier. */
685 struct pivot_argument *args;
692 /* Numbers resulting from calculations. */
693 struct pivot_value *pivot_value_new_number (double);
694 struct pivot_value *pivot_value_new_integer (double);
696 /* Values from data. */
697 struct pivot_value *pivot_value_new_var_value (
698 const struct variable *, const union value *);
699 struct pivot_value *pivot_value_new_value (const union value *, int width,
700 const struct fmt_spec *,
701 const char *encoding);
703 /* Values from variable names. */
704 struct pivot_value *pivot_value_new_variable (const struct variable *);
706 /* Values from text strings. */
707 struct pivot_value *pivot_value_new_text (const char *);
708 struct pivot_value *pivot_value_new_text_format (const char *, ...)
709 #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
710 __attribute__((format(gnu_printf, 1, 2)));
712 __attribute__((format(__printf__, 1, 2)));
715 struct pivot_value *pivot_value_new_user_text (const char *, size_t length);
716 struct pivot_value *pivot_value_new_user_text_nocopy (char *);
719 void pivot_value_add_footnote (struct pivot_value *, const struct pivot_footnote *);
721 /* Numeric formats. */
722 void pivot_value_set_rc (const struct pivot_table *, struct pivot_value *,
725 /* Converting a pivot_value to a string for display. */
726 char *pivot_value_to_string (const struct pivot_value *,
727 enum settings_value_show show_values,
728 enum settings_value_show show_variables);
729 void pivot_value_format (const struct pivot_value *,
730 enum settings_value_show show_values,
731 enum settings_value_show show_variables,
733 bool pivot_value_format_body (const struct pivot_value *,
734 enum settings_value_show show_values,
735 enum settings_value_show show_variables,
738 void pivot_value_destroy (struct pivot_value *);
741 void pivot_value_get_style (struct pivot_value *,
742 const struct font_style *base_font_style,
743 const struct cell_style *base_cell_style,
744 struct table_area_style *);
745 void pivot_value_set_style (struct pivot_value *,
746 const struct table_area_style *);
748 /* Template arguments. */
749 struct pivot_argument
752 struct pivot_value **values;
755 void pivot_argument_uninit (struct pivot_argument *);
757 /* One piece of data within a pivot table. */
760 struct hmap_node hmap_node; /* In struct pivot_table's 'cells' hmap. */
761 struct pivot_value *value;
762 unsigned int idx[]; /* One index per table dimension. */
765 #endif /* output/pivot-table.h */