2 PSPP - a program for statistical analysis.
3 Copyright (C) 2012 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <gsl/gsl_cdf.h>
24 #include "libpspp/assertion.h"
25 #include "libpspp/message.h"
26 #include "libpspp/pool.h"
29 #include "data/dataset.h"
30 #include "data/dictionary.h"
31 #include "data/casegrouper.h"
32 #include "data/casereader.h"
33 #include "data/casewriter.h"
34 #include "data/caseproto.h"
35 #include "data/subcase.h"
38 #include "data/format.h"
40 #include "math/interaction.h"
41 #include "math/box-whisker.h"
42 #include "math/categoricals.h"
43 #include "math/histogram.h"
44 #include "math/moments.h"
46 #include "math/sort.h"
47 #include "math/order-stats.h"
48 #include "math/percentiles.h"
49 #include "math/tukey-hinges.h"
50 #include "math/trimmed-mean.h"
52 #include "output/charts/boxplot.h"
53 #include "output/charts/np-plot.h"
54 #include "output/charts/plot-hist.h"
56 #include "language/command.h"
57 #include "language/lexer/lexer.h"
58 #include "language/lexer/value-parser.h"
59 #include "language/lexer/variable-parser.h"
61 #include "output/tab.h"
64 #define _(msgid) gettext (msgid)
65 #define N_(msgid) msgid
74 /* Indices for the ex_proto member (below) */
87 /* A caseproto used to contain the data subsets under examination,
89 struct caseproto *ex_proto;
92 const struct variable **dep_vars;
95 struct interaction **iacts;
97 enum mv_class exclude;
99 const struct dictionary *dict;
101 struct categoricals *cats;
103 /* how many extremities to display */
112 /* Test options require that casenumbers are known */
115 /* The case index of the ID value (or -1) if not applicable */
120 size_t n_percentiles;
126 enum bp_mode boxplot_mode;
128 const struct variable *id_var;
130 const struct variable *wv;
135 /* The value of this extremity */
138 /* Either the casenumber or the value of the variable specified
139 by the /ID subcommand which corresponds to this extremity */
143 struct exploratory_stats
150 /* Most operations need a sorted reader/writer */
151 struct casewriter *sorted_writer;
152 struct casereader *sorted_reader;
154 struct extremity *minima;
155 struct extremity *maxima;
158 Minimum should alway equal mimima[0].val.
159 Likewise, maximum should alway equal maxima[0].val.
160 This redundancy exists as an optimisation effort.
161 Some statistics (eg histogram) require early calculation
167 struct trimmed_mean *trimmed_mean;
168 struct percentile *quartiles[3];
169 struct percentile **percentiles;
171 struct tukey_hinges *hinges;
173 /* The data for the NP Plots */
176 struct histogram *histogram;
178 /* The data for the box plots */
179 struct box_whisker *box_whisker;
184 /* The minimum weight */
189 /* Returns an array of (iact->n_vars) pointers to union value initialised to NULL.
190 The caller must free this array when no longer required. */
191 static const union value **
192 previous_value_alloc (const struct interaction *iact)
196 const union value **prev_val = xcalloc (iact->n_vars, sizeof (*prev_val));
198 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
199 prev_val[ivar_idx] = NULL;
204 /* Set the contents of PREV_VAL to the values of C indexed by the variables of IACT */
206 previous_value_record (const struct interaction *iact, const struct ccase *c, const union value **prev_val)
211 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
213 const struct variable *ivar = iact->vars[ivar_idx];
214 const int width = var_get_width (ivar);
215 const union value *val = case_data (c, ivar);
217 if (prev_val[ivar_idx])
218 if (! value_equal (prev_val[ivar_idx], val, width))
225 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
227 const struct variable *ivar = iact->vars[ivar_idx];
228 const union value *val = case_data (c, ivar);
230 prev_val[ivar_idx] = val;
237 show_boxplot_grouped (const struct examine *cmd, int iact_idx)
241 const struct interaction *iact = cmd->iacts[iact_idx];
242 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
244 for (v = 0; v < cmd->n_dep_vars; ++v)
246 double y_min = DBL_MAX;
247 double y_max = -DBL_MAX;
249 struct boxplot *boxplot;
251 ds_init_empty (&title);
253 if (iact->n_vars > 0)
256 ds_init_empty (&istr);
257 interaction_to_string (iact, &istr);
258 ds_put_format (&title, _("Boxplot of %s vs. %s"),
259 var_to_string (cmd->dep_vars[v]),
264 ds_put_format (&title, _("Boxplot of %s"), var_to_string (cmd->dep_vars[v]));
266 for (grp = 0; grp < n_cats; ++grp)
268 const struct exploratory_stats *es =
269 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
271 if ( y_min > es[v].minimum)
272 y_min = es[v].minimum;
274 if ( y_max < es[v].maximum)
275 y_max = es[v].maximum;
278 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
282 for (grp = 0; grp < n_cats; ++grp)
287 const struct ccase *c =
288 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
290 const struct exploratory_stats *es =
291 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
293 ds_init_empty (&label);
294 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
296 const struct variable *ivar = iact->vars[ivar_idx];
297 const union value *val = case_data (c, ivar);
299 ds_put_cstr (&label, var_to_string (ivar));
300 ds_put_cstr (&label, " = ");
301 var_append_value_name (ivar, val, &label);
302 ds_put_cstr (&label, "; ");
305 boxplot_add_box (boxplot, es[v].box_whisker, ds_cstr (&label));
310 boxplot_submit (boxplot);
315 show_boxplot_variabled (const struct examine *cmd, int iact_idx)
318 const struct interaction *iact = cmd->iacts[iact_idx];
319 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
321 for (grp = 0; grp < n_cats; ++grp)
323 struct boxplot *boxplot;
325 double y_min = DBL_MAX;
326 double y_max = -DBL_MAX;
328 const struct ccase *c =
329 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
332 ds_init_empty (&title);
334 for (v = 0; v < cmd->n_dep_vars; ++v)
336 const struct exploratory_stats *es =
337 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
339 if ( y_min > es[v].minimum)
340 y_min = es[v].minimum;
342 if ( y_max < es[v].maximum)
343 y_max = es[v].maximum;
346 if ( iact->n_vars == 0)
347 ds_put_format (&title, _("Boxplot"));
352 ds_init_empty (&label);
353 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
355 const struct variable *ivar = iact->vars[ivar_idx];
356 const union value *val = case_data (c, ivar);
358 ds_put_cstr (&label, var_to_string (ivar));
359 ds_put_cstr (&label, " = ");
360 var_append_value_name (ivar, val, &label);
361 ds_put_cstr (&label, "; ");
364 ds_put_format (&title, _("Boxplot of %s"),
370 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
374 for (v = 0; v < cmd->n_dep_vars; ++v)
376 const struct exploratory_stats *es =
377 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
379 boxplot_add_box (boxplot, es[v].box_whisker,
380 var_to_string (cmd->dep_vars[v]));
383 boxplot_submit (boxplot);
389 show_npplot (const struct examine *cmd, int iact_idx)
391 const struct interaction *iact = cmd->iacts[iact_idx];
392 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
396 for (v = 0; v < cmd->n_dep_vars; ++v)
399 for (grp = 0; grp < n_cats; ++grp)
401 struct chart_item *npp, *dnpp;
402 struct casereader *reader;
406 const struct ccase *c =
407 categoricals_get_case_by_category_real (cmd->cats,
410 const struct exploratory_stats *es =
411 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
414 ds_init_cstr (&label,
415 var_to_string (cmd->dep_vars[v]));
417 if ( iact->n_vars > 0)
419 ds_put_cstr (&label, " (");
420 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
422 const struct variable *ivar = iact->vars[ivar_idx];
423 const union value *val = case_data (c, ivar);
425 ds_put_cstr (&label, var_to_string (ivar));
426 ds_put_cstr (&label, " = ");
427 var_append_value_name (ivar, val, &label);
428 ds_put_cstr (&label, "; ");
431 ds_put_cstr (&label, ")");
435 reader = casewriter_make_reader (np->writer);
438 npp = np_plot_create (np, reader, ds_cstr (&label));
439 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
441 if (npp == NULL || dnpp == NULL)
443 msg (MW, _("Not creating NP plot because data set is empty."));
444 chart_item_unref (npp);
445 chart_item_unref (dnpp);
449 chart_item_submit (npp);
450 chart_item_submit (dnpp);
452 casereader_destroy (reader);
461 show_histogram (const struct examine *cmd, int iact_idx)
463 const struct interaction *iact = cmd->iacts[iact_idx];
464 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
468 for (v = 0; v < cmd->n_dep_vars; ++v)
471 for (grp = 0; grp < n_cats; ++grp)
475 const struct ccase *c =
476 categoricals_get_case_by_category_real (cmd->cats,
479 const struct exploratory_stats *es =
480 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
483 ds_init_cstr (&label,
484 var_to_string (cmd->dep_vars[v]));
486 if ( iact->n_vars > 0)
488 ds_put_cstr (&label, " (");
489 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
491 const struct variable *ivar = iact->vars[ivar_idx];
492 const union value *val = case_data (c, ivar);
494 ds_put_cstr (&label, var_to_string (ivar));
495 ds_put_cstr (&label, " = ");
496 var_append_value_name (ivar, val, &label);
497 ds_put_cstr (&label, "; ");
500 ds_put_cstr (&label, ")");
504 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
507 ( histogram_chart_create (es[v].histogram->gsl_hist,
508 ds_cstr (&label), n, mean,
518 percentiles_report (const struct examine *cmd, int iact_idx)
520 const struct interaction *iact = cmd->iacts[iact_idx];
522 const int heading_columns = 1 + iact->n_vars + 1;
523 const int heading_rows = 2;
526 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
528 const int rows_per_cat = 2;
529 const int rows_per_var = n_cats * rows_per_cat;
531 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
532 const int nc = heading_columns + cmd->n_percentiles;
534 t = tab_create (nc, nr);
535 tab_title (t, _("Percentiles"));
537 tab_headers (t, heading_columns, 0, heading_rows, 0);
539 /* Internal Vertical lines */
540 tab_box (t, -1, -1, -1, TAL_1,
541 heading_columns, 0, nc - 1, nr - 1);
544 tab_box (t, TAL_2, TAL_2, -1, -1,
545 0, 0, nc - 1, nr - 1);
547 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
548 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
550 tab_joint_text (t, heading_columns, 0,
552 TAT_TITLE | TAB_CENTER,
556 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
559 for (i = 0; i < cmd->n_percentiles; ++i)
561 tab_text_format (t, heading_columns + i, 1,
562 TAT_TITLE | TAB_CENTER,
563 _("%g"), cmd->ptiles[i]);
566 for (i = 0; i < iact->n_vars; ++i)
571 var_to_string (iact->vars[i])
579 tab_vline (t, TAL_1, heading_columns - 1, heading_rows, nr - 1);
581 for (v = 0; v < cmd->n_dep_vars; ++v)
583 const union value **prev_vals = previous_value_alloc (iact);
587 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
590 0, heading_rows + v * rows_per_var,
591 TAT_TITLE | TAB_LEFT,
592 var_to_string (cmd->dep_vars[v])
595 for (i = 0; i < n_cats; ++i)
597 const struct ccase *c =
598 categoricals_get_case_by_category_real (cmd->cats,
601 const struct exploratory_stats *ess =
602 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
604 const struct exploratory_stats *es = ess + v;
606 int diff_idx = previous_value_record (iact, c, prev_vals);
611 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
613 const struct variable *ivar = iact->vars[ivar_idx];
614 const union value *val = case_data (c, ivar);
616 if (( diff_idx != -1 && diff_idx <= ivar_idx)
620 ds_init_empty (&str);
621 var_append_value_name (ivar, val, &str);
625 heading_rows + v * rows_per_var + i * rows_per_cat,
626 TAT_TITLE | TAB_LEFT,
634 if ( diff_idx != -1 && diff_idx < iact->n_vars)
636 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
637 heading_rows + v * rows_per_var + i * rows_per_cat
641 tab_text (t, heading_columns - 1,
642 heading_rows + v * rows_per_var + i * rows_per_cat,
643 TAT_TITLE | TAB_LEFT,
644 gettext (ptile_alg_desc [cmd->pc_alg]));
646 tukey_hinges_calculate (es->hinges, hinges);
648 for (p = 0; p < cmd->n_percentiles; ++p)
650 tab_double (t, heading_columns + p,
651 heading_rows + v * rows_per_var + i * rows_per_cat,
653 percentile_calculate (es->percentiles[p], cmd->pc_alg),
656 if (cmd->ptiles[p] == 25.0)
658 tab_double (t, heading_columns + p,
659 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
664 else if (cmd->ptiles[p] == 50.0)
666 tab_double (t, heading_columns + p,
667 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
672 else if (cmd->ptiles[p] == 75.0)
674 tab_double (t, heading_columns + p,
675 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
683 tab_text (t, heading_columns - 1,
684 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
685 TAT_TITLE | TAB_LEFT,
686 _("Tukey's Hinges"));
697 descriptives_report (const struct examine *cmd, int iact_idx)
699 const struct interaction *iact = cmd->iacts[iact_idx];
701 const int heading_columns = 1 + iact->n_vars + 2;
702 const int heading_rows = 1;
705 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
707 const int rows_per_cat = 13;
708 const int rows_per_var = n_cats * rows_per_cat;
710 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
711 const int nc = 2 + heading_columns;
713 t = tab_create (nc, nr);
714 tab_title (t, _("Descriptives"));
716 tab_headers (t, heading_columns, 0, heading_rows, 0);
718 /* Internal Vertical lines */
719 tab_box (t, -1, -1, -1, TAL_1,
720 heading_columns, 0, nc - 1, nr - 1);
723 tab_box (t, TAL_2, TAL_2, -1, -1,
724 0, 0, nc - 1, nr - 1);
726 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
727 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
730 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
733 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
736 for (i = 0; i < iact->n_vars; ++i)
741 var_to_string (iact->vars[i])
745 for (v = 0; v < cmd->n_dep_vars; ++v)
747 const union value **prev_val = previous_value_alloc (iact);
751 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
754 0, heading_rows + v * rows_per_var,
755 TAT_TITLE | TAB_LEFT,
756 var_to_string (cmd->dep_vars[v])
759 for (i = 0; i < n_cats; ++i)
761 const struct ccase *c =
762 categoricals_get_case_by_category_real (cmd->cats,
765 const struct exploratory_stats *ess =
766 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
768 const struct exploratory_stats *es = ess + v;
770 const int diff_idx = previous_value_record (iact, c, prev_val);
772 double m0, m1, m2, m3, m4;
775 moments_calculate (es->mom, &m0, &m1, &m2, &m3, &m4);
777 tval = gsl_cdf_tdist_Qinv ((1.0 - cmd->conf) / 2.0, m0 - 1.0);
779 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
781 const struct variable *ivar = iact->vars[ivar_idx];
782 const union value *val = case_data (c, ivar);
784 if (( diff_idx != -1 && diff_idx <= ivar_idx)
788 ds_init_empty (&str);
789 var_append_value_name (ivar, val, &str);
793 heading_rows + v * rows_per_var + i * rows_per_cat,
794 TAT_TITLE | TAB_LEFT,
802 if ( diff_idx != -1 && diff_idx < iact->n_vars)
804 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
805 heading_rows + v * rows_per_var + i * rows_per_cat
811 heading_rows + v * rows_per_var + i * rows_per_cat,
817 1 + iact->n_vars + 2,
818 heading_rows + v * rows_per_var + i * rows_per_cat,
822 1 + iact->n_vars + 3,
823 heading_rows + v * rows_per_var + i * rows_per_cat,
824 0, calc_semean (m2, m0), 0);
828 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
830 _("%g%% Confidence Interval for Mean"),
835 1 + iact->n_vars + 1,
836 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
842 1 + iact->n_vars + 2,
843 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
844 0, m1 - tval * calc_semean (m2, m0), 0);
848 1 + iact->n_vars + 1,
849 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
855 1 + iact->n_vars + 2,
856 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
857 0, m1 + tval * calc_semean (m2, m0), 0);
862 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
868 1 + iact->n_vars + 2,
869 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
871 trimmed_mean_calculate (es->trimmed_mean),
876 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
882 1 + iact->n_vars + 2,
883 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
885 percentile_calculate (es->quartiles[1], cmd->pc_alg),
891 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
897 1 + iact->n_vars + 2,
898 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
903 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
909 1 + iact->n_vars + 2,
910 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
915 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
921 1 + iact->n_vars + 2,
922 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
929 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
935 1 + iact->n_vars + 2,
936 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
943 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
949 1 + iact->n_vars + 2,
950 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
952 es->maxima[0].val - es->minima[0].val,
957 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
959 _("Interquartile Range")
964 1 + iact->n_vars + 2,
965 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
967 percentile_calculate (es->quartiles[2], cmd->pc_alg) -
968 percentile_calculate (es->quartiles[0], cmd->pc_alg),
976 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
982 1 + iact->n_vars + 2,
983 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
987 1 + iact->n_vars + 3,
988 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
989 0, calc_seskew (m0), 0);
993 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
999 1 + iact->n_vars + 2,
1000 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1004 1 + iact->n_vars + 3,
1005 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1006 0, calc_sekurt (m0), 0);
1016 extremes_report (const struct examine *cmd, int iact_idx)
1018 const struct interaction *iact = cmd->iacts[iact_idx];
1020 const int heading_columns = 1 + iact->n_vars + 2;
1021 const int heading_rows = 1;
1022 struct tab_table *t;
1024 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1026 const int rows_per_cat = 2 * cmd->disp_extremes;
1027 const int rows_per_var = n_cats * rows_per_cat;
1029 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
1030 const int nc = 2 + heading_columns;
1032 t = tab_create (nc, nr);
1033 tab_title (t, _("Extreme Values"));
1035 tab_headers (t, heading_columns, 0, heading_rows, 0);
1037 /* Internal Vertical lines */
1038 tab_box (t, -1, -1, -1, TAL_1,
1039 heading_columns, 0, nc - 1, nr - 1);
1041 /* External Frame */
1042 tab_box (t, TAL_2, TAL_2, -1, -1,
1043 0, 0, nc - 1, nr - 1);
1045 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1046 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1050 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1051 var_to_string (cmd->id_var));
1053 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1056 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
1059 for (i = 0; i < iact->n_vars; ++i)
1064 var_to_string (iact->vars[i])
1068 for (v = 0; v < cmd->n_dep_vars; ++v)
1070 const union value **prev_val = previous_value_alloc (iact);
1074 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
1077 0, heading_rows + v * rows_per_var,
1079 var_to_string (cmd->dep_vars[v])
1082 for (i = 0; i < n_cats; ++i)
1085 const struct ccase *c =
1086 categoricals_get_case_by_category_real (cmd->cats, iact_idx, i);
1088 const struct exploratory_stats *ess =
1089 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1091 const struct exploratory_stats *es = ess + v;
1093 int diff_idx = previous_value_record (iact, c, prev_val);
1095 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1097 const struct variable *ivar = iact->vars[ivar_idx];
1098 const union value *val = case_data (c, ivar);
1100 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1104 ds_init_empty (&str);
1105 var_append_value_name (ivar, val, &str);
1109 heading_rows + v * rows_per_var + i * rows_per_cat,
1110 TAT_TITLE | TAB_LEFT,
1118 if ( diff_idx != -1 && diff_idx < iact->n_vars)
1120 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1121 heading_rows + v * rows_per_var + i * rows_per_cat
1126 heading_columns - 2,
1127 heading_rows + v * rows_per_var + i * rows_per_cat,
1132 tab_hline (t, TAL_1, heading_columns - 2, nc - 1,
1133 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes
1137 heading_columns - 2,
1138 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes,
1142 for (e = 0 ; e < cmd->disp_extremes; ++e)
1145 heading_columns - 1,
1146 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1151 /* The casenumber */
1154 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1156 es->maxima[e].identity,
1161 heading_columns + 1,
1162 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1170 heading_columns - 1,
1171 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1176 /* The casenumber */
1179 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1181 es->minima[e].identity,
1185 heading_columns + 1,
1186 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1200 summary_report (const struct examine *cmd, int iact_idx)
1202 const struct interaction *iact = cmd->iacts[iact_idx];
1204 const int heading_columns = 1 + iact->n_vars;
1205 const int heading_rows = 3;
1206 struct tab_table *t;
1208 const struct fmt_spec *wfmt = cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
1210 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1212 const int nr = heading_rows + n_cats * cmd->n_dep_vars;
1213 const int nc = 6 + heading_columns;
1215 t = tab_create (nc, nr);
1216 tab_title (t, _("Case Processing Summary"));
1218 tab_headers (t, heading_columns, 0, heading_rows, 0);
1220 /* Internal Vertical lines */
1221 tab_box (t, -1, -1, -1, TAL_1,
1222 heading_columns, 0, nc - 1, nr - 1);
1224 /* External Frame */
1225 tab_box (t, TAL_2, TAL_2, -1, -1,
1226 0, 0, nc - 1, nr - 1);
1228 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1229 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1231 tab_joint_text (t, heading_columns, 0,
1232 nc - 1, 0, TAB_CENTER | TAT_TITLE, _("Cases"));
1235 heading_columns + 1, 1,
1236 TAB_CENTER | TAT_TITLE, _("Valid"));
1239 heading_columns + 2, 1,
1240 heading_columns + 3, 1,
1241 TAB_CENTER | TAT_TITLE, _("Missing"));
1244 heading_columns + 4, 1,
1245 heading_columns + 5, 1,
1246 TAB_CENTER | TAT_TITLE, _("Total"));
1248 for (i = 0; i < 3; ++i)
1250 tab_text (t, heading_columns + i * 2, 2, TAB_CENTER | TAT_TITLE,
1252 tab_text (t, heading_columns + i * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1256 for (i = 0; i < iact->n_vars; ++i)
1261 var_to_string (iact->vars[i])
1266 for (v = 0; v < cmd->n_dep_vars; ++v)
1269 const union value **prev_values = previous_value_alloc (iact);
1272 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * n_cats);
1275 0, heading_rows + n_cats * v,
1277 var_to_string (cmd->dep_vars[v])
1281 for (i = 0; i < n_cats; ++i)
1284 const struct exploratory_stats *es;
1286 const struct ccase *c =
1287 categoricals_get_case_by_category_real (cmd->cats,
1291 int diff_idx = previous_value_record (iact, c, prev_values);
1293 if ( diff_idx != -1 && diff_idx < iact->n_vars - 1)
1294 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1295 heading_rows + n_cats * v + i );
1297 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1299 const struct variable *ivar = iact->vars[ivar_idx];
1300 const union value *val = case_data (c, ivar);
1302 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1306 ds_init_empty (&str);
1307 var_append_value_name (ivar, val, &str);
1310 1 + ivar_idx, heading_rows + n_cats * v + i,
1311 TAT_TITLE | TAB_LEFT,
1321 es = categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1324 total = es[v].missing + es[v].non_missing;
1326 heading_columns + 0,
1327 heading_rows + n_cats * v + i,
1334 heading_columns + 1,
1335 heading_rows + n_cats * v + i,
1338 100.0 * es[v].non_missing / total
1343 heading_columns + 2,
1344 heading_rows + n_cats * v + i,
1350 heading_columns + 3,
1351 heading_rows + n_cats * v + i,
1354 100.0 * es[v].missing / total
1357 heading_columns + 4,
1358 heading_rows + n_cats * v + i,
1363 /* This can only be 100% can't it? */
1365 heading_columns + 5,
1366 heading_rows + n_cats * v + i,
1369 100.0 * (es[v].missing + es[v].non_missing)/ total
1375 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
1376 tab_hline (t, TAL_1, heading_columns, nc - 1, 2);
1382 /* Match a variable.
1383 If the match succeeds, the variable will be placed in VAR.
1384 Returns true if successful */
1386 lex_match_variable (struct lexer *lexer,
1387 const struct dictionary *dict, const struct variable **var)
1389 if (lex_token (lexer) != T_ID)
1393 *var = parse_variable_const (lexer, dict);
1400 /* Attempt to parse an interaction from LEXER */
1401 static struct interaction *
1402 parse_interaction (struct lexer *lexer, struct examine *ex)
1404 const struct variable *v = NULL;
1405 struct interaction *iact = NULL;
1407 if ( lex_match_variable (lexer, ex->dict, &v))
1409 iact = interaction_create (v);
1411 while (lex_match (lexer, T_BY))
1413 if (!lex_match_variable (lexer, ex->dict, &v))
1415 interaction_destroy (iact);
1418 interaction_add_variable (iact, v);
1420 lex_match (lexer, T_COMMA);
1428 create_n (const void *aux1, void *aux2 UNUSED)
1432 const struct examine *examine = aux1;
1433 struct exploratory_stats *es = pool_calloc (examine->pool, examine->n_dep_vars, sizeof (*es));
1434 struct subcase ordering;
1435 subcase_init (&ordering, 0, 0, SC_ASCEND);
1437 for (v = 0; v < examine->n_dep_vars; v++)
1439 es[v].sorted_writer = sort_create_writer (&ordering, examine->ex_proto);
1440 es[v].sorted_reader = NULL;
1442 es[v].mom = moments_create (MOMENT_KURTOSIS);
1443 es[v].cmin = DBL_MAX;
1445 es[v].maximum = -DBL_MAX;
1446 es[v].minimum = DBL_MAX;
1449 subcase_destroy (&ordering);
1454 update_n (const void *aux1, void *aux2 UNUSED, void *user_data,
1455 const struct ccase *c, double weight)
1458 const struct examine *examine = aux1;
1459 struct exploratory_stats *es = user_data;
1461 for (v = 0; v < examine->n_dep_vars; v++)
1463 struct ccase *outcase ;
1464 const struct variable *var = examine->dep_vars[v];
1465 const double x = case_data (c, var)->f;
1467 if (var_is_value_missing (var, case_data (c, var), examine->exclude))
1469 es[v].missing += weight;
1473 outcase = case_create (examine->ex_proto);
1475 if (x > es[v].maximum)
1478 if (x < es[v].minimum)
1481 es[v].non_missing += weight;
1483 moments_pass_one (es[v].mom, x, weight);
1485 /* Save the value and the casenumber to the writer */
1486 case_data_rw_idx (outcase, EX_VAL)->f = x;
1487 if ( examine->id_idx != -1)
1488 case_data_rw_idx (outcase, EX_ID)->f = case_data_idx (c, examine->id_idx)->f;
1490 case_data_rw_idx (outcase, EX_WT)->f = weight;
1494 if (es[v].cmin > weight)
1495 es[v].cmin = weight;
1497 casewriter_write (es[v].sorted_writer, outcase);
1502 calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data)
1505 const struct examine *examine = aux1;
1506 struct exploratory_stats *es = user_data;
1508 for (v = 0; v < examine->n_dep_vars; v++)
1511 casenumber imin = 0;
1512 double imax = es[v].cc;
1513 struct casereader *reader;
1515 casenumber total_cases;
1517 if (examine->histogram)
1520 histogram_create (10, es[v].minimum, es[v].maximum);
1523 es[v].sorted_reader = casewriter_make_reader (es[v].sorted_writer);
1524 total_cases = casereader_count_cases (es[v].sorted_reader);
1525 es[v].sorted_writer = NULL;
1527 es[v].maxima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].maxima));
1528 es[v].minima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].minima));
1530 for (reader = casereader_clone (es[v].sorted_reader);
1531 (c = casereader_read (reader)) != NULL; case_unref (c))
1533 const double val = case_data_idx (c, EX_VAL)->f;
1534 const double wt = case_data_idx (c, EX_WT)->f; /* FIXME: What about fractional weights ??? */
1536 moments_pass_two (es[v].mom, val, wt);
1538 if (es[v].histogram)
1539 histogram_add (es[v].histogram, val, wt);
1541 if (imin < examine->calc_extremes)
1544 for (x = imin; x < examine->calc_extremes; ++x)
1546 struct extremity *min = &es[v].minima[x];
1548 min->identity = case_data_idx (c, EX_ID)->f;
1554 if (imax < examine->calc_extremes)
1558 for (x = imax; x < imax + wt; ++x)
1560 struct extremity *max;
1562 if (x >= examine->calc_extremes)
1565 max = &es[v].maxima[x];
1567 max->identity = case_data_idx (c, EX_ID)->f;
1571 casereader_destroy (reader);
1573 if (examine->calc_extremes > 0)
1575 assert (es[v].minima[0].val == es[v].minimum);
1576 assert (es[v].maxima[0].val == es[v].maximum);
1580 const int n_os = 5 + examine->n_percentiles;
1581 struct order_stats **os ;
1582 es[v].percentiles = pool_calloc (examine->pool, examine->n_percentiles, sizeof (*es[v].percentiles));
1584 es[v].trimmed_mean = trimmed_mean_create (es[v].cc, 0.05);
1586 os = xcalloc (n_os, sizeof *os);
1587 os[0] = &es[v].trimmed_mean->parent;
1589 es[v].quartiles[0] = percentile_create (0.25, es[v].cc);
1590 es[v].quartiles[1] = percentile_create (0.5, es[v].cc);
1591 es[v].quartiles[2] = percentile_create (0.75, es[v].cc);
1593 os[1] = &es[v].quartiles[0]->parent;
1594 os[2] = &es[v].quartiles[1]->parent;
1595 os[3] = &es[v].quartiles[2]->parent;
1597 es[v].hinges = tukey_hinges_create (es[v].cc, es[v].cmin);
1598 os[4] = &es[v].hinges->parent;
1600 for (i = 0; i < examine->n_percentiles; ++i)
1602 es[v].percentiles[i] = percentile_create (examine->ptiles[i] / 100.00, es[v].cc);
1603 os[5 + i] = &es[v].percentiles[i]->parent;
1606 order_stats_accumulate_idx (os, n_os,
1607 casereader_clone (es[v].sorted_reader),
1613 if (examine->boxplot)
1615 struct order_stats *os;
1617 es[v].box_whisker = box_whisker_create (es[v].hinges,
1620 os = &es[v].box_whisker->parent;
1621 order_stats_accumulate_idx (&os, 1,
1622 casereader_clone (es[v].sorted_reader),
1626 if (examine->npplot)
1628 double n, mean, var;
1629 struct order_stats *os;
1631 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
1633 es[v].np = np_create (n, mean, var);
1635 os = &es[v].np->parent;
1637 order_stats_accumulate_idx (&os, 1,
1638 casereader_clone (es[v].sorted_reader),
1646 cleanup_exploratory_stats (struct examine *cmd)
1649 for (i = 0; i < cmd->n_iacts; ++i)
1652 const size_t n_cats = categoricals_n_count (cmd->cats, i);
1654 for (v = 0; v < cmd->n_dep_vars; ++v)
1657 for (grp = 0; grp < n_cats; ++grp)
1660 const struct exploratory_stats *es =
1661 categoricals_get_user_data_by_category_real (cmd->cats, i, grp);
1663 struct order_stats *os = &es[v].hinges->parent;
1664 struct statistic *stat = &os->parent;
1665 stat->destroy (stat);
1667 for (q = 0; q < 3 ; q++)
1669 os = &es[v].quartiles[q]->parent;
1671 stat->destroy (stat);
1674 for (q = 0; q < cmd->n_percentiles ; q++)
1676 os = &es[v].percentiles[q]->parent;
1678 stat->destroy (stat);
1681 os = &es[v].trimmed_mean->parent;
1683 stat->destroy (stat);
1685 os = &es[v].np->parent;
1689 stat->destroy (stat);
1692 statistic_destroy (&es[v].histogram->parent);
1693 moments_destroy (es[v].mom);
1695 casereader_destroy (es[v].sorted_reader);
1703 run_examine (struct examine *cmd, struct casereader *input)
1707 struct casereader *reader;
1709 struct payload payload;
1710 payload.create = create_n;
1711 payload.update = update_n;
1712 payload.destroy = calculate_n;
1714 cmd->wv = dict_get_weight (cmd->dict);
1718 = categoricals_create (cmd->iacts, cmd->n_iacts,
1719 cmd->wv, cmd->exclude);
1721 categoricals_set_payload (cmd->cats, &payload, cmd, NULL);
1723 if (cmd->casenumbers)
1725 struct ccase *c = casereader_peek (input, 0);
1728 cmd->id_idx = var_get_case_index (cmd->id_var);
1731 cmd->id_idx = case_get_value_cnt (c);
1732 input = casereader_create_arithmetic_sequence (input, 1.0, 1.0);
1738 /* FIXME: Filter out missing factor variables */
1740 /* Remove cases on a listwise basis if requested */
1741 if ( cmd->missing_pw == false)
1742 input = casereader_create_filter_missing (input,
1749 for (reader = input;
1750 (c = casereader_read (reader)) != NULL; case_unref (c))
1752 categoricals_update (cmd->cats, c);
1754 casereader_destroy (reader);
1755 categoricals_done (cmd->cats);
1757 for (i = 0; i < cmd->n_iacts; ++i)
1759 summary_report (cmd, i);
1761 if (cmd->disp_extremes > 0)
1762 extremes_report (cmd, i);
1764 if (cmd->n_percentiles > 0)
1765 percentiles_report (cmd, i);
1769 switch (cmd->boxplot_mode)
1772 show_boxplot_grouped (cmd, i);
1775 show_boxplot_variabled (cmd, i);
1784 show_histogram (cmd, i);
1787 show_npplot (cmd, i);
1789 if (cmd->descriptives)
1790 descriptives_report (cmd, i);
1793 cleanup_exploratory_stats (cmd);
1794 categoricals_destroy (cmd->cats);
1799 cmd_examine (struct lexer *lexer, struct dataset *ds)
1802 bool nototals_seen = false;
1803 bool totals_seen = false;
1805 struct interaction **iacts_mem = NULL;
1806 struct examine examine;
1807 bool percentiles_seen = false;
1809 examine.casenumbers = false;
1810 examine.missing_pw = false;
1811 examine.disp_extremes = 0;
1812 examine.calc_extremes = 0;
1813 examine.descriptives = false;
1814 examine.conf = 0.95;
1815 examine.pc_alg = PC_HAVERAGE;
1816 examine.ptiles = NULL;
1817 examine.n_percentiles = 0;
1819 examine.boxplot_mode = BP_GROUPS;
1821 examine.ex_proto = caseproto_create ();
1822 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */
1823 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* id */
1824 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */
1826 examine.pool = pool_create ();
1828 /* Allocate space for the first interaction.
1829 This is interaction is an empty one (for the totals).
1830 If no totals are requested, we will simply ignore this
1833 examine.n_iacts = 1;
1834 examine.iacts = iacts_mem = pool_zalloc (examine.pool, sizeof (struct interaction *));
1835 examine.iacts[0] = interaction_create (NULL);
1837 examine.exclude = MV_ANY;
1838 examine.histogram = false;
1839 examine.npplot = false;
1840 examine.boxplot = false;
1842 examine.dict = dataset_dict (ds);
1844 /* Accept an optional, completely pointless "/VARIABLES=" */
1845 lex_match (lexer, T_SLASH);
1846 if (lex_match_id (lexer, "VARIABLES"))
1848 if (! lex_force_match (lexer, T_EQUALS) )
1852 if (!parse_variables_const (lexer, examine.dict,
1853 &examine.dep_vars, &examine.n_dep_vars,
1854 PV_NO_DUPLICATE | PV_NUMERIC))
1857 if (lex_match (lexer, T_BY))
1859 struct interaction *iact = NULL;
1862 iact = parse_interaction (lexer, &examine);
1867 pool_nrealloc (examine.pool, iacts_mem,
1869 sizeof (*iacts_mem));
1871 iacts_mem[examine.n_iacts - 1] = iact;
1878 while (lex_token (lexer) != T_ENDCMD)
1880 lex_match (lexer, T_SLASH);
1882 if (lex_match_id (lexer, "STATISTICS"))
1884 lex_match (lexer, T_EQUALS);
1886 while (lex_token (lexer) != T_ENDCMD
1887 && lex_token (lexer) != T_SLASH)
1889 if (lex_match_id (lexer, "DESCRIPTIVES"))
1891 examine.descriptives = true;
1893 else if (lex_match_id (lexer, "EXTREME"))
1896 if (lex_match (lexer, T_LPAREN))
1898 extr = lex_integer (lexer);
1902 msg (MW, _("%s may not be negative. Using default value (%g)."), "EXTREME", 5.0);
1907 if (! lex_force_match (lexer, T_RPAREN))
1910 examine.disp_extremes = extr;
1912 else if (lex_match_id (lexer, "NONE"))
1915 else if (lex_match (lexer, T_ALL))
1917 if (examine.disp_extremes == 0)
1918 examine.disp_extremes = 5;
1922 lex_error (lexer, NULL);
1927 else if (lex_match_id (lexer, "PERCENTILES"))
1929 percentiles_seen = true;
1930 if (lex_match (lexer, T_LPAREN))
1932 while (lex_is_number (lexer))
1934 double p = lex_number (lexer);
1936 if ( p <= 0 || p >= 100.0)
1939 _("Percentiles must lie in the range (0, 100)"));
1943 examine.n_percentiles++;
1945 xrealloc (examine.ptiles,
1946 sizeof (*examine.ptiles) *
1947 examine.n_percentiles);
1949 examine.ptiles[examine.n_percentiles - 1] = p;
1952 lex_match (lexer, T_COMMA);
1954 if (!lex_force_match (lexer, T_RPAREN))
1958 lex_match (lexer, T_EQUALS);
1960 while (lex_token (lexer) != T_ENDCMD
1961 && lex_token (lexer) != T_SLASH)
1963 if (lex_match_id (lexer, "HAVERAGE"))
1965 examine.pc_alg = PC_HAVERAGE;
1967 else if (lex_match_id (lexer, "WAVERAGE"))
1969 examine.pc_alg = PC_WAVERAGE;
1971 else if (lex_match_id (lexer, "ROUND"))
1973 examine.pc_alg = PC_ROUND;
1975 else if (lex_match_id (lexer, "EMPIRICAL"))
1977 examine.pc_alg = PC_EMPIRICAL;
1979 else if (lex_match_id (lexer, "AEMPIRICAL"))
1981 examine.pc_alg = PC_AEMPIRICAL;
1983 else if (lex_match_id (lexer, "NONE"))
1985 examine.pc_alg = PC_NONE;
1989 lex_error (lexer, NULL);
1994 else if (lex_match_id (lexer, "TOTAL"))
1998 else if (lex_match_id (lexer, "NOTOTAL"))
2000 nototals_seen = true;
2002 else if (lex_match_id (lexer, "MISSING"))
2004 lex_match (lexer, T_EQUALS);
2006 while (lex_token (lexer) != T_ENDCMD
2007 && lex_token (lexer) != T_SLASH)
2009 if (lex_match_id (lexer, "LISTWISE"))
2011 examine.missing_pw = false;
2013 else if (lex_match_id (lexer, "PAIRWISE"))
2015 examine.missing_pw = true;
2017 else if (lex_match_id (lexer, "EXCLUDE"))
2019 examine.exclude = MV_ANY;
2021 else if (lex_match_id (lexer, "INCLUDE"))
2023 examine.exclude = MV_SYSTEM;
2027 lex_error (lexer, NULL);
2032 else if (lex_match_id (lexer, "COMPARE"))
2034 lex_match (lexer, T_EQUALS);
2035 if (lex_match_id (lexer, "VARIABLES"))
2037 examine.boxplot_mode = BP_VARIABLES;
2039 else if (lex_match_id (lexer, "GROUPS"))
2041 examine.boxplot_mode = BP_GROUPS;
2045 lex_error (lexer, NULL);
2049 else if (lex_match_id (lexer, "PLOT"))
2051 lex_match (lexer, T_EQUALS);
2053 while (lex_token (lexer) != T_ENDCMD
2054 && lex_token (lexer) != T_SLASH)
2056 if (lex_match_id (lexer, "BOXPLOT"))
2058 examine.boxplot = true;
2060 else if (lex_match_id (lexer, "NPPLOT"))
2062 examine.npplot = true;
2064 else if (lex_match_id (lexer, "HISTOGRAM"))
2066 examine.histogram = true;
2068 else if (lex_match_id (lexer, "NONE"))
2070 examine.histogram = false;
2071 examine.npplot = false;
2072 examine.boxplot = false;
2074 else if (lex_match (lexer, T_ALL))
2076 examine.histogram = true;
2077 examine.npplot = true;
2078 examine.boxplot = true;
2082 lex_error (lexer, NULL);
2085 lex_match (lexer, T_COMMA);
2088 else if (lex_match_id (lexer, "CINTERVAL"))
2090 if ( !lex_force_num (lexer))
2093 examine.conf = lex_number (lexer);
2096 else if (lex_match_id (lexer, "ID"))
2098 lex_match (lexer, T_EQUALS);
2100 examine.id_var = parse_variable_const (lexer, examine.dict);
2104 lex_error (lexer, NULL);
2109 if ( totals_seen && nototals_seen)
2111 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
2115 /* If totals have been requested or if there are no factors
2116 in this analysis, then the totals need to be included. */
2117 if ( !nototals_seen || examine.n_iacts == 1)
2119 examine.iacts = &iacts_mem[0];
2124 examine.iacts = &iacts_mem[1];
2128 if (examine.disp_extremes > 0)
2130 examine.calc_extremes = examine.disp_extremes;
2131 examine.casenumbers = true;
2134 if (examine.boxplot)
2136 examine.casenumbers = true;
2140 if (examine.descriptives && examine.calc_extremes == 0)
2142 /* Descriptives always displays the max and min */
2143 examine.calc_extremes = 1;
2146 if (percentiles_seen && examine.n_percentiles == 0)
2148 examine.n_percentiles = 7;
2149 examine.ptiles = xcalloc (examine.n_percentiles,
2150 sizeof (*examine.ptiles));
2152 examine.ptiles[0] = 5;
2153 examine.ptiles[1] = 10;
2154 examine.ptiles[2] = 25;
2155 examine.ptiles[3] = 50;
2156 examine.ptiles[4] = 75;
2157 examine.ptiles[5] = 90;
2158 examine.ptiles[6] = 95;
2161 assert (examine.calc_extremes >= examine.disp_extremes);
2163 struct casegrouper *grouper;
2164 struct casereader *group;
2167 grouper = casegrouper_create_splits (proc_open (ds), examine.dict);
2168 while (casegrouper_get_next_group (grouper, &group))
2169 run_examine (&examine, group);
2170 ok = casegrouper_destroy (grouper);
2171 ok = proc_commit (ds) && ok;
2174 caseproto_unref (examine.ex_proto);
2176 for (i = 0; i < examine.n_iacts; ++i)
2177 interaction_destroy (examine.iacts[i]);
2179 free (examine.ptiles);
2180 free (examine.dep_vars);
2181 pool_destroy (examine.pool);
2186 caseproto_unref (examine.ex_proto);
2187 for (i = 0; i < examine.n_iacts; ++i)
2188 interaction_destroy (examine.iacts[i]);
2189 free (examine.dep_vars);
2190 free (examine.ptiles);
2191 pool_destroy (examine.pool);