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/chart-geometry.h"
44 #include "math/histogram.h"
45 #include "math/moments.h"
47 #include "math/sort.h"
48 #include "math/order-stats.h"
49 #include "math/percentiles.h"
50 #include "math/tukey-hinges.h"
51 #include "math/trimmed-mean.h"
53 #include "output/charts/boxplot.h"
54 #include "output/charts/np-plot.h"
55 #include "output/charts/plot-hist.h"
57 #include "language/command.h"
58 #include "language/lexer/lexer.h"
59 #include "language/lexer/value-parser.h"
60 #include "language/lexer/variable-parser.h"
62 #include "output/tab.h"
65 #define _(msgid) gettext (msgid)
66 #define N_(msgid) msgid
75 /* Indices for the ex_proto member (below) */
88 /* A caseproto used to contain the data subsets under examination,
90 struct caseproto *ex_proto;
93 const struct variable **dep_vars;
96 struct interaction **iacts;
98 enum mv_class exclude;
100 const struct dictionary *dict;
102 struct categoricals *cats;
104 /* how many extremities to display */
113 /* Test options require that casenumbers are known */
116 /* The case index of the ID value (or -1) if not applicable */
121 size_t n_percentiles;
127 enum bp_mode boxplot_mode;
129 const struct variable *id_var;
131 const struct variable *wv;
136 /* The value of this extremity */
139 /* Either the casenumber or the value of the variable specified
140 by the /ID subcommand which corresponds to this extremity */
144 struct exploratory_stats
151 /* Most operations need a sorted reader/writer */
152 struct casewriter *sorted_writer;
153 struct casereader *sorted_reader;
155 struct extremity *minima;
156 struct extremity *maxima;
159 Minimum should alway equal mimima[0].val.
160 Likewise, maximum should alway equal maxima[0].val.
161 This redundancy exists as an optimisation effort.
162 Some statistics (eg histogram) require early calculation
168 struct trimmed_mean *trimmed_mean;
169 struct percentile *quartiles[3];
170 struct percentile **percentiles;
172 struct tukey_hinges *hinges;
174 /* The data for the NP Plots */
177 struct histogram *histogram;
179 /* The data for the box plots */
180 struct box_whisker *box_whisker;
185 /* The minimum weight */
190 /* Returns an array of (iact->n_vars) pointers to union value initialised to NULL.
191 The caller must free this array when no longer required. */
192 static const union value **
193 previous_value_alloc (const struct interaction *iact)
197 const union value **prev_val = xcalloc (iact->n_vars, sizeof (*prev_val));
199 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
200 prev_val[ivar_idx] = NULL;
205 /* Set the contents of PREV_VAL to the values of C indexed by the variables of IACT */
207 previous_value_record (const struct interaction *iact, const struct ccase *c, const union value **prev_val)
212 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
214 const struct variable *ivar = iact->vars[ivar_idx];
215 const int width = var_get_width (ivar);
216 const union value *val = case_data (c, ivar);
218 if (prev_val[ivar_idx])
219 if (! value_equal (prev_val[ivar_idx], val, width))
226 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
228 const struct variable *ivar = iact->vars[ivar_idx];
229 const union value *val = case_data (c, ivar);
231 prev_val[ivar_idx] = val;
238 show_boxplot_grouped (const struct examine *cmd, int iact_idx)
242 const struct interaction *iact = cmd->iacts[iact_idx];
243 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
245 for (v = 0; v < cmd->n_dep_vars; ++v)
247 double y_min = DBL_MAX;
248 double y_max = -DBL_MAX;
250 struct boxplot *boxplot;
252 ds_init_empty (&title);
254 if (iact->n_vars > 0)
257 ds_init_empty (&istr);
258 interaction_to_string (iact, &istr);
259 ds_put_format (&title, _("Boxplot of %s vs. %s"),
260 var_to_string (cmd->dep_vars[v]),
265 ds_put_format (&title, _("Boxplot of %s"), var_to_string (cmd->dep_vars[v]));
267 for (grp = 0; grp < n_cats; ++grp)
269 const struct exploratory_stats *es =
270 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
272 if ( y_min > es[v].minimum)
273 y_min = es[v].minimum;
275 if ( y_max < es[v].maximum)
276 y_max = es[v].maximum;
279 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
283 for (grp = 0; grp < n_cats; ++grp)
288 const struct ccase *c =
289 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
291 const struct exploratory_stats *es =
292 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
294 ds_init_empty (&label);
295 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
297 const struct variable *ivar = iact->vars[ivar_idx];
298 const union value *val = case_data (c, ivar);
300 ds_put_cstr (&label, var_to_string (ivar));
301 ds_put_cstr (&label, " = ");
302 var_append_value_name (ivar, val, &label);
303 ds_put_cstr (&label, "; ");
306 boxplot_add_box (boxplot, es[v].box_whisker, ds_cstr (&label));
311 boxplot_submit (boxplot);
316 show_boxplot_variabled (const struct examine *cmd, int iact_idx)
319 const struct interaction *iact = cmd->iacts[iact_idx];
320 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
322 for (grp = 0; grp < n_cats; ++grp)
324 struct boxplot *boxplot;
326 double y_min = DBL_MAX;
327 double y_max = -DBL_MAX;
329 const struct ccase *c =
330 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
333 ds_init_empty (&title);
335 for (v = 0; v < cmd->n_dep_vars; ++v)
337 const struct exploratory_stats *es =
338 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
340 if ( y_min > es[v].minimum)
341 y_min = es[v].minimum;
343 if ( y_max < es[v].maximum)
344 y_max = es[v].maximum;
347 if ( iact->n_vars == 0)
348 ds_put_format (&title, _("Boxplot"));
353 ds_init_empty (&label);
354 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
356 const struct variable *ivar = iact->vars[ivar_idx];
357 const union value *val = case_data (c, ivar);
359 ds_put_cstr (&label, var_to_string (ivar));
360 ds_put_cstr (&label, " = ");
361 var_append_value_name (ivar, val, &label);
362 ds_put_cstr (&label, "; ");
365 ds_put_format (&title, _("Boxplot of %s"),
371 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
375 for (v = 0; v < cmd->n_dep_vars; ++v)
377 const struct exploratory_stats *es =
378 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
380 boxplot_add_box (boxplot, es[v].box_whisker,
381 var_to_string (cmd->dep_vars[v]));
384 boxplot_submit (boxplot);
390 show_npplot (const struct examine *cmd, int iact_idx)
392 const struct interaction *iact = cmd->iacts[iact_idx];
393 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
397 for (v = 0; v < cmd->n_dep_vars; ++v)
400 for (grp = 0; grp < n_cats; ++grp)
402 struct chart_item *npp, *dnpp;
403 struct casereader *reader;
407 const struct ccase *c =
408 categoricals_get_case_by_category_real (cmd->cats,
411 const struct exploratory_stats *es =
412 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
415 ds_init_cstr (&label,
416 var_to_string (cmd->dep_vars[v]));
418 if ( iact->n_vars > 0)
420 ds_put_cstr (&label, " (");
421 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
423 const struct variable *ivar = iact->vars[ivar_idx];
424 const union value *val = case_data (c, ivar);
426 ds_put_cstr (&label, var_to_string (ivar));
427 ds_put_cstr (&label, " = ");
428 var_append_value_name (ivar, val, &label);
429 ds_put_cstr (&label, "; ");
432 ds_put_cstr (&label, ")");
436 reader = casewriter_make_reader (np->writer);
439 npp = np_plot_create (np, reader, ds_cstr (&label));
440 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
442 if (npp == NULL || dnpp == NULL)
444 msg (MW, _("Not creating NP plot because data set is empty."));
445 chart_item_unref (npp);
446 chart_item_unref (dnpp);
450 chart_item_submit (npp);
451 chart_item_submit (dnpp);
453 casereader_destroy (reader);
462 show_histogram (const struct examine *cmd, int iact_idx)
464 const struct interaction *iact = cmd->iacts[iact_idx];
465 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
469 for (v = 0; v < cmd->n_dep_vars; ++v)
472 for (grp = 0; grp < n_cats; ++grp)
476 const struct ccase *c =
477 categoricals_get_case_by_category_real (cmd->cats,
480 const struct exploratory_stats *es =
481 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
484 ds_init_cstr (&label,
485 var_to_string (cmd->dep_vars[v]));
487 if ( iact->n_vars > 0)
489 ds_put_cstr (&label, " (");
490 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
492 const struct variable *ivar = iact->vars[ivar_idx];
493 const union value *val = case_data (c, ivar);
495 ds_put_cstr (&label, var_to_string (ivar));
496 ds_put_cstr (&label, " = ");
497 var_append_value_name (ivar, val, &label);
498 ds_put_cstr (&label, "; ");
501 ds_put_cstr (&label, ")");
505 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
508 ( histogram_chart_create (es[v].histogram->gsl_hist,
509 ds_cstr (&label), n, mean,
519 percentiles_report (const struct examine *cmd, int iact_idx)
521 const struct interaction *iact = cmd->iacts[iact_idx];
523 const int heading_columns = 1 + iact->n_vars + 1;
524 const int heading_rows = 2;
527 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
529 const int rows_per_cat = 2;
530 const int rows_per_var = n_cats * rows_per_cat;
532 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
533 const int nc = heading_columns + cmd->n_percentiles;
535 t = tab_create (nc, nr);
536 tab_title (t, _("Percentiles"));
538 tab_headers (t, heading_columns, 0, heading_rows, 0);
540 /* Internal Vertical lines */
541 tab_box (t, -1, -1, -1, TAL_1,
542 heading_columns, 0, nc - 1, nr - 1);
545 tab_box (t, TAL_2, TAL_2, -1, -1,
546 0, 0, nc - 1, nr - 1);
548 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
549 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
551 tab_joint_text (t, heading_columns, 0,
553 TAT_TITLE | TAB_CENTER,
557 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
560 for (i = 0; i < cmd->n_percentiles; ++i)
562 tab_text_format (t, heading_columns + i, 1,
563 TAT_TITLE | TAB_CENTER,
564 _("%g"), cmd->ptiles[i]);
567 for (i = 0; i < iact->n_vars; ++i)
572 var_to_string (iact->vars[i])
580 tab_vline (t, TAL_1, heading_columns - 1, heading_rows, nr - 1);
582 for (v = 0; v < cmd->n_dep_vars; ++v)
584 const union value **prev_vals = previous_value_alloc (iact);
588 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
591 0, heading_rows + v * rows_per_var,
592 TAT_TITLE | TAB_LEFT,
593 var_to_string (cmd->dep_vars[v])
596 for (i = 0; i < n_cats; ++i)
598 const struct ccase *c =
599 categoricals_get_case_by_category_real (cmd->cats,
602 const struct exploratory_stats *ess =
603 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
605 const struct exploratory_stats *es = ess + v;
607 int diff_idx = previous_value_record (iact, c, prev_vals);
612 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
614 const struct variable *ivar = iact->vars[ivar_idx];
615 const union value *val = case_data (c, ivar);
617 if (( diff_idx != -1 && diff_idx <= ivar_idx)
621 ds_init_empty (&str);
622 var_append_value_name (ivar, val, &str);
626 heading_rows + v * rows_per_var + i * rows_per_cat,
627 TAT_TITLE | TAB_LEFT,
635 if ( diff_idx != -1 && diff_idx < iact->n_vars)
637 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
638 heading_rows + v * rows_per_var + i * rows_per_cat
642 tab_text (t, heading_columns - 1,
643 heading_rows + v * rows_per_var + i * rows_per_cat,
644 TAT_TITLE | TAB_LEFT,
645 gettext (ptile_alg_desc [cmd->pc_alg]));
647 tukey_hinges_calculate (es->hinges, hinges);
649 for (p = 0; p < cmd->n_percentiles; ++p)
651 tab_double (t, heading_columns + p,
652 heading_rows + v * rows_per_var + i * rows_per_cat,
654 percentile_calculate (es->percentiles[p], cmd->pc_alg),
657 if (cmd->ptiles[p] == 25.0)
659 tab_double (t, heading_columns + p,
660 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
665 else if (cmd->ptiles[p] == 50.0)
667 tab_double (t, heading_columns + p,
668 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
673 else if (cmd->ptiles[p] == 75.0)
675 tab_double (t, heading_columns + p,
676 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
684 tab_text (t, heading_columns - 1,
685 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
686 TAT_TITLE | TAB_LEFT,
687 _("Tukey's Hinges"));
698 descriptives_report (const struct examine *cmd, int iact_idx)
700 const struct interaction *iact = cmd->iacts[iact_idx];
702 const int heading_columns = 1 + iact->n_vars + 2;
703 const int heading_rows = 1;
706 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
708 const int rows_per_cat = 13;
709 const int rows_per_var = n_cats * rows_per_cat;
711 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
712 const int nc = 2 + heading_columns;
714 t = tab_create (nc, nr);
715 tab_title (t, _("Descriptives"));
717 tab_headers (t, heading_columns, 0, heading_rows, 0);
719 /* Internal Vertical lines */
720 tab_box (t, -1, -1, -1, TAL_1,
721 heading_columns, 0, nc - 1, nr - 1);
724 tab_box (t, TAL_2, TAL_2, -1, -1,
725 0, 0, nc - 1, nr - 1);
727 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
728 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
731 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
734 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
737 for (i = 0; i < iact->n_vars; ++i)
742 var_to_string (iact->vars[i])
746 for (v = 0; v < cmd->n_dep_vars; ++v)
748 const union value **prev_val = previous_value_alloc (iact);
752 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
755 0, heading_rows + v * rows_per_var,
756 TAT_TITLE | TAB_LEFT,
757 var_to_string (cmd->dep_vars[v])
760 for (i = 0; i < n_cats; ++i)
762 const struct ccase *c =
763 categoricals_get_case_by_category_real (cmd->cats,
766 const struct exploratory_stats *ess =
767 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
769 const struct exploratory_stats *es = ess + v;
771 const int diff_idx = previous_value_record (iact, c, prev_val);
773 double m0, m1, m2, m3, m4;
776 moments_calculate (es->mom, &m0, &m1, &m2, &m3, &m4);
778 tval = gsl_cdf_tdist_Qinv ((1.0 - cmd->conf) / 2.0, m0 - 1.0);
780 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
782 const struct variable *ivar = iact->vars[ivar_idx];
783 const union value *val = case_data (c, ivar);
785 if (( diff_idx != -1 && diff_idx <= ivar_idx)
789 ds_init_empty (&str);
790 var_append_value_name (ivar, val, &str);
794 heading_rows + v * rows_per_var + i * rows_per_cat,
795 TAT_TITLE | TAB_LEFT,
803 if ( diff_idx != -1 && diff_idx < iact->n_vars)
805 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
806 heading_rows + v * rows_per_var + i * rows_per_cat
812 heading_rows + v * rows_per_var + i * rows_per_cat,
818 1 + iact->n_vars + 2,
819 heading_rows + v * rows_per_var + i * rows_per_cat,
823 1 + iact->n_vars + 3,
824 heading_rows + v * rows_per_var + i * rows_per_cat,
825 0, calc_semean (m2, m0), 0);
829 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
831 _("%g%% Confidence Interval for Mean"),
836 1 + iact->n_vars + 1,
837 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
843 1 + iact->n_vars + 2,
844 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
845 0, m1 - tval * calc_semean (m2, m0), 0);
849 1 + iact->n_vars + 1,
850 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
856 1 + iact->n_vars + 2,
857 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
858 0, m1 + tval * calc_semean (m2, m0), 0);
863 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
869 1 + iact->n_vars + 2,
870 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
872 trimmed_mean_calculate (es->trimmed_mean),
877 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
883 1 + iact->n_vars + 2,
884 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
886 percentile_calculate (es->quartiles[1], cmd->pc_alg),
892 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
898 1 + iact->n_vars + 2,
899 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
904 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
910 1 + iact->n_vars + 2,
911 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
916 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
922 1 + iact->n_vars + 2,
923 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
930 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
936 1 + iact->n_vars + 2,
937 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
944 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
950 1 + iact->n_vars + 2,
951 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
953 es->maxima[0].val - es->minima[0].val,
958 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
960 _("Interquartile Range")
965 1 + iact->n_vars + 2,
966 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
968 percentile_calculate (es->quartiles[2], cmd->pc_alg) -
969 percentile_calculate (es->quartiles[0], cmd->pc_alg),
977 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
983 1 + iact->n_vars + 2,
984 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
988 1 + iact->n_vars + 3,
989 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
990 0, calc_seskew (m0), 0);
994 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1000 1 + iact->n_vars + 2,
1001 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1005 1 + iact->n_vars + 3,
1006 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1007 0, calc_sekurt (m0), 0);
1017 extremes_report (const struct examine *cmd, int iact_idx)
1019 const struct interaction *iact = cmd->iacts[iact_idx];
1021 const int heading_columns = 1 + iact->n_vars + 2;
1022 const int heading_rows = 1;
1023 struct tab_table *t;
1025 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1027 const int rows_per_cat = 2 * cmd->disp_extremes;
1028 const int rows_per_var = n_cats * rows_per_cat;
1030 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
1031 const int nc = 2 + heading_columns;
1033 t = tab_create (nc, nr);
1034 tab_title (t, _("Extreme Values"));
1036 tab_headers (t, heading_columns, 0, heading_rows, 0);
1038 /* Internal Vertical lines */
1039 tab_box (t, -1, -1, -1, TAL_1,
1040 heading_columns, 0, nc - 1, nr - 1);
1042 /* External Frame */
1043 tab_box (t, TAL_2, TAL_2, -1, -1,
1044 0, 0, nc - 1, nr - 1);
1046 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1047 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1051 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1052 var_to_string (cmd->id_var));
1054 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1057 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
1060 for (i = 0; i < iact->n_vars; ++i)
1065 var_to_string (iact->vars[i])
1069 for (v = 0; v < cmd->n_dep_vars; ++v)
1071 const union value **prev_val = previous_value_alloc (iact);
1075 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
1078 0, heading_rows + v * rows_per_var,
1080 var_to_string (cmd->dep_vars[v])
1083 for (i = 0; i < n_cats; ++i)
1086 const struct ccase *c =
1087 categoricals_get_case_by_category_real (cmd->cats, iact_idx, i);
1089 const struct exploratory_stats *ess =
1090 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1092 const struct exploratory_stats *es = ess + v;
1094 int diff_idx = previous_value_record (iact, c, prev_val);
1096 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1098 const struct variable *ivar = iact->vars[ivar_idx];
1099 const union value *val = case_data (c, ivar);
1101 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1105 ds_init_empty (&str);
1106 var_append_value_name (ivar, val, &str);
1110 heading_rows + v * rows_per_var + i * rows_per_cat,
1111 TAT_TITLE | TAB_LEFT,
1119 if ( diff_idx != -1 && diff_idx < iact->n_vars)
1121 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1122 heading_rows + v * rows_per_var + i * rows_per_cat
1127 heading_columns - 2,
1128 heading_rows + v * rows_per_var + i * rows_per_cat,
1133 tab_hline (t, TAL_1, heading_columns - 2, nc - 1,
1134 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes
1138 heading_columns - 2,
1139 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes,
1143 for (e = 0 ; e < cmd->disp_extremes; ++e)
1146 heading_columns - 1,
1147 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1152 /* The casenumber */
1155 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1157 es->maxima[e].identity,
1162 heading_columns + 1,
1163 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1171 heading_columns - 1,
1172 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1177 /* The casenumber */
1180 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1182 es->minima[e].identity,
1186 heading_columns + 1,
1187 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1201 summary_report (const struct examine *cmd, int iact_idx)
1203 const struct interaction *iact = cmd->iacts[iact_idx];
1205 const int heading_columns = 1 + iact->n_vars;
1206 const int heading_rows = 3;
1207 struct tab_table *t;
1209 const struct fmt_spec *wfmt = cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
1211 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1213 const int nr = heading_rows + n_cats * cmd->n_dep_vars;
1214 const int nc = 6 + heading_columns;
1216 t = tab_create (nc, nr);
1217 tab_title (t, _("Case Processing Summary"));
1219 tab_headers (t, heading_columns, 0, heading_rows, 0);
1221 /* Internal Vertical lines */
1222 tab_box (t, -1, -1, -1, TAL_1,
1223 heading_columns, 0, nc - 1, nr - 1);
1225 /* External Frame */
1226 tab_box (t, TAL_2, TAL_2, -1, -1,
1227 0, 0, nc - 1, nr - 1);
1229 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1230 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1232 tab_joint_text (t, heading_columns, 0,
1233 nc - 1, 0, TAB_CENTER | TAT_TITLE, _("Cases"));
1236 heading_columns + 1, 1,
1237 TAB_CENTER | TAT_TITLE, _("Valid"));
1240 heading_columns + 2, 1,
1241 heading_columns + 3, 1,
1242 TAB_CENTER | TAT_TITLE, _("Missing"));
1245 heading_columns + 4, 1,
1246 heading_columns + 5, 1,
1247 TAB_CENTER | TAT_TITLE, _("Total"));
1249 for (i = 0; i < 3; ++i)
1251 tab_text (t, heading_columns + i * 2, 2, TAB_CENTER | TAT_TITLE,
1253 tab_text (t, heading_columns + i * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1257 for (i = 0; i < iact->n_vars; ++i)
1262 var_to_string (iact->vars[i])
1267 for (v = 0; v < cmd->n_dep_vars; ++v)
1270 const union value **prev_values = previous_value_alloc (iact);
1273 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * n_cats);
1276 0, heading_rows + n_cats * v,
1278 var_to_string (cmd->dep_vars[v])
1282 for (i = 0; i < n_cats; ++i)
1285 const struct exploratory_stats *es;
1287 const struct ccase *c =
1288 categoricals_get_case_by_category_real (cmd->cats,
1292 int diff_idx = previous_value_record (iact, c, prev_values);
1294 if ( diff_idx != -1 && diff_idx < iact->n_vars - 1)
1295 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1296 heading_rows + n_cats * v + i );
1298 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1300 const struct variable *ivar = iact->vars[ivar_idx];
1301 const union value *val = case_data (c, ivar);
1303 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1307 ds_init_empty (&str);
1308 var_append_value_name (ivar, val, &str);
1311 1 + ivar_idx, heading_rows + n_cats * v + i,
1312 TAT_TITLE | TAB_LEFT,
1322 es = categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1325 total = es[v].missing + es[v].non_missing;
1327 heading_columns + 0,
1328 heading_rows + n_cats * v + i,
1335 heading_columns + 1,
1336 heading_rows + n_cats * v + i,
1339 100.0 * es[v].non_missing / total
1344 heading_columns + 2,
1345 heading_rows + n_cats * v + i,
1351 heading_columns + 3,
1352 heading_rows + n_cats * v + i,
1355 100.0 * es[v].missing / total
1358 heading_columns + 4,
1359 heading_rows + n_cats * v + i,
1364 /* This can only be 100% can't it? */
1366 heading_columns + 5,
1367 heading_rows + n_cats * v + i,
1370 100.0 * (es[v].missing + es[v].non_missing)/ total
1376 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
1377 tab_hline (t, TAL_1, heading_columns, nc - 1, 2);
1383 /* Match a variable.
1384 If the match succeeds, the variable will be placed in VAR.
1385 Returns true if successful */
1387 lex_match_variable (struct lexer *lexer,
1388 const struct dictionary *dict, const struct variable **var)
1390 if (lex_token (lexer) != T_ID)
1394 *var = parse_variable_const (lexer, dict);
1401 /* Attempt to parse an interaction from LEXER */
1402 static struct interaction *
1403 parse_interaction (struct lexer *lexer, struct examine *ex)
1405 const struct variable *v = NULL;
1406 struct interaction *iact = NULL;
1408 if ( lex_match_variable (lexer, ex->dict, &v))
1410 iact = interaction_create (v);
1412 while (lex_match (lexer, T_BY))
1414 if (!lex_match_variable (lexer, ex->dict, &v))
1416 interaction_destroy (iact);
1419 interaction_add_variable (iact, v);
1421 lex_match (lexer, T_COMMA);
1429 create_n (const void *aux1, void *aux2 UNUSED)
1433 const struct examine *examine = aux1;
1434 struct exploratory_stats *es = pool_calloc (examine->pool, examine->n_dep_vars, sizeof (*es));
1435 struct subcase ordering;
1436 subcase_init (&ordering, 0, 0, SC_ASCEND);
1438 for (v = 0; v < examine->n_dep_vars; v++)
1440 es[v].sorted_writer = sort_create_writer (&ordering, examine->ex_proto);
1441 es[v].sorted_reader = NULL;
1443 es[v].mom = moments_create (MOMENT_KURTOSIS);
1444 es[v].cmin = DBL_MAX;
1446 es[v].maximum = -DBL_MAX;
1447 es[v].minimum = DBL_MAX;
1450 subcase_destroy (&ordering);
1455 update_n (const void *aux1, void *aux2 UNUSED, void *user_data,
1456 const struct ccase *c, double weight)
1459 const struct examine *examine = aux1;
1460 struct exploratory_stats *es = user_data;
1462 for (v = 0; v < examine->n_dep_vars; v++)
1464 struct ccase *outcase ;
1465 const struct variable *var = examine->dep_vars[v];
1466 const double x = case_data (c, var)->f;
1468 if (var_is_value_missing (var, case_data (c, var), examine->exclude))
1470 es[v].missing += weight;
1474 outcase = case_create (examine->ex_proto);
1476 if (x > es[v].maximum)
1479 if (x < es[v].minimum)
1482 es[v].non_missing += weight;
1484 moments_pass_one (es[v].mom, x, weight);
1486 /* Save the value and the casenumber to the writer */
1487 case_data_rw_idx (outcase, EX_VAL)->f = x;
1488 if ( examine->id_idx != -1)
1489 case_data_rw_idx (outcase, EX_ID)->f = case_data_idx (c, examine->id_idx)->f;
1491 case_data_rw_idx (outcase, EX_WT)->f = weight;
1495 if (es[v].cmin > weight)
1496 es[v].cmin = weight;
1498 casewriter_write (es[v].sorted_writer, outcase);
1503 calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data)
1506 const struct examine *examine = aux1;
1507 struct exploratory_stats *es = user_data;
1509 for (v = 0; v < examine->n_dep_vars; v++)
1512 casenumber imin = 0;
1513 double imax = es[v].cc;
1514 struct casereader *reader;
1516 casenumber total_cases;
1518 if (examine->histogram)
1521 double bin_width = abs (es[v].minimum - es[v].maximum)
1522 / (1 + log2 (es[v].cc))
1525 bin_width = chart_rounded_tick (bin_width);
1528 histogram_create (bin_width, es[v].minimum, es[v].maximum);
1531 es[v].sorted_reader = casewriter_make_reader (es[v].sorted_writer);
1532 total_cases = casereader_count_cases (es[v].sorted_reader);
1533 es[v].sorted_writer = NULL;
1535 es[v].maxima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].maxima));
1536 es[v].minima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].minima));
1538 for (reader = casereader_clone (es[v].sorted_reader);
1539 (c = casereader_read (reader)) != NULL; case_unref (c))
1541 const double val = case_data_idx (c, EX_VAL)->f;
1542 const double wt = case_data_idx (c, EX_WT)->f; /* FIXME: What about fractional weights ??? */
1544 moments_pass_two (es[v].mom, val, wt);
1546 if (es[v].histogram)
1547 histogram_add (es[v].histogram, val, wt);
1549 if (imin < examine->calc_extremes)
1552 for (x = imin; x < examine->calc_extremes; ++x)
1554 struct extremity *min = &es[v].minima[x];
1556 min->identity = case_data_idx (c, EX_ID)->f;
1562 if (imax < examine->calc_extremes)
1566 for (x = imax; x < imax + wt; ++x)
1568 struct extremity *max;
1570 if (x >= examine->calc_extremes)
1573 max = &es[v].maxima[x];
1575 max->identity = case_data_idx (c, EX_ID)->f;
1579 casereader_destroy (reader);
1581 if (examine->calc_extremes > 0)
1583 assert (es[v].minima[0].val == es[v].minimum);
1584 assert (es[v].maxima[0].val == es[v].maximum);
1588 const int n_os = 5 + examine->n_percentiles;
1589 struct order_stats **os ;
1590 es[v].percentiles = pool_calloc (examine->pool, examine->n_percentiles, sizeof (*es[v].percentiles));
1592 es[v].trimmed_mean = trimmed_mean_create (es[v].cc, 0.05);
1594 os = xcalloc (n_os, sizeof *os);
1595 os[0] = &es[v].trimmed_mean->parent;
1597 es[v].quartiles[0] = percentile_create (0.25, es[v].cc);
1598 es[v].quartiles[1] = percentile_create (0.5, es[v].cc);
1599 es[v].quartiles[2] = percentile_create (0.75, es[v].cc);
1601 os[1] = &es[v].quartiles[0]->parent;
1602 os[2] = &es[v].quartiles[1]->parent;
1603 os[3] = &es[v].quartiles[2]->parent;
1605 es[v].hinges = tukey_hinges_create (es[v].cc, es[v].cmin);
1606 os[4] = &es[v].hinges->parent;
1608 for (i = 0; i < examine->n_percentiles; ++i)
1610 es[v].percentiles[i] = percentile_create (examine->ptiles[i] / 100.00, es[v].cc);
1611 os[5 + i] = &es[v].percentiles[i]->parent;
1614 order_stats_accumulate_idx (os, n_os,
1615 casereader_clone (es[v].sorted_reader),
1621 if (examine->boxplot)
1623 struct order_stats *os;
1625 es[v].box_whisker = box_whisker_create (es[v].hinges,
1628 os = &es[v].box_whisker->parent;
1629 order_stats_accumulate_idx (&os, 1,
1630 casereader_clone (es[v].sorted_reader),
1634 if (examine->npplot)
1636 double n, mean, var;
1637 struct order_stats *os;
1639 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
1641 es[v].np = np_create (n, mean, var);
1643 os = &es[v].np->parent;
1645 order_stats_accumulate_idx (&os, 1,
1646 casereader_clone (es[v].sorted_reader),
1654 cleanup_exploratory_stats (struct examine *cmd)
1657 for (i = 0; i < cmd->n_iacts; ++i)
1660 const size_t n_cats = categoricals_n_count (cmd->cats, i);
1662 for (v = 0; v < cmd->n_dep_vars; ++v)
1665 for (grp = 0; grp < n_cats; ++grp)
1668 const struct exploratory_stats *es =
1669 categoricals_get_user_data_by_category_real (cmd->cats, i, grp);
1671 struct order_stats *os = &es[v].hinges->parent;
1672 struct statistic *stat = &os->parent;
1673 stat->destroy (stat);
1675 for (q = 0; q < 3 ; q++)
1677 os = &es[v].quartiles[q]->parent;
1679 stat->destroy (stat);
1682 for (q = 0; q < cmd->n_percentiles ; q++)
1684 os = &es[v].percentiles[q]->parent;
1686 stat->destroy (stat);
1689 os = &es[v].trimmed_mean->parent;
1691 stat->destroy (stat);
1693 os = &es[v].np->parent;
1697 stat->destroy (stat);
1700 statistic_destroy (&es[v].histogram->parent);
1701 moments_destroy (es[v].mom);
1703 casereader_destroy (es[v].sorted_reader);
1711 run_examine (struct examine *cmd, struct casereader *input)
1715 struct casereader *reader;
1717 struct payload payload;
1718 payload.create = create_n;
1719 payload.update = update_n;
1720 payload.destroy = calculate_n;
1722 cmd->wv = dict_get_weight (cmd->dict);
1726 = categoricals_create (cmd->iacts, cmd->n_iacts,
1727 cmd->wv, cmd->exclude);
1729 categoricals_set_payload (cmd->cats, &payload, cmd, NULL);
1731 if (cmd->casenumbers)
1733 struct ccase *c = casereader_peek (input, 0);
1736 cmd->id_idx = var_get_case_index (cmd->id_var);
1739 cmd->id_idx = case_get_value_cnt (c);
1740 input = casereader_create_arithmetic_sequence (input, 1.0, 1.0);
1746 /* FIXME: Filter out missing factor variables */
1748 /* Remove cases on a listwise basis if requested */
1749 if ( cmd->missing_pw == false)
1750 input = casereader_create_filter_missing (input,
1757 for (reader = input;
1758 (c = casereader_read (reader)) != NULL; case_unref (c))
1760 categoricals_update (cmd->cats, c);
1762 casereader_destroy (reader);
1763 categoricals_done (cmd->cats);
1765 for (i = 0; i < cmd->n_iacts; ++i)
1767 summary_report (cmd, i);
1769 if (cmd->disp_extremes > 0)
1770 extremes_report (cmd, i);
1772 if (cmd->n_percentiles > 0)
1773 percentiles_report (cmd, i);
1777 switch (cmd->boxplot_mode)
1780 show_boxplot_grouped (cmd, i);
1783 show_boxplot_variabled (cmd, i);
1792 show_histogram (cmd, i);
1795 show_npplot (cmd, i);
1797 if (cmd->descriptives)
1798 descriptives_report (cmd, i);
1801 cleanup_exploratory_stats (cmd);
1802 categoricals_destroy (cmd->cats);
1807 cmd_examine (struct lexer *lexer, struct dataset *ds)
1810 bool nototals_seen = false;
1811 bool totals_seen = false;
1813 struct interaction **iacts_mem = NULL;
1814 struct examine examine;
1815 bool percentiles_seen = false;
1817 examine.casenumbers = false;
1818 examine.missing_pw = false;
1819 examine.disp_extremes = 0;
1820 examine.calc_extremes = 0;
1821 examine.descriptives = false;
1822 examine.conf = 0.95;
1823 examine.pc_alg = PC_HAVERAGE;
1824 examine.ptiles = NULL;
1825 examine.n_percentiles = 0;
1827 examine.boxplot_mode = BP_GROUPS;
1829 examine.ex_proto = caseproto_create ();
1830 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */
1831 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* id */
1832 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */
1834 examine.pool = pool_create ();
1836 /* Allocate space for the first interaction.
1837 This is interaction is an empty one (for the totals).
1838 If no totals are requested, we will simply ignore this
1841 examine.n_iacts = 1;
1842 examine.iacts = iacts_mem = pool_zalloc (examine.pool, sizeof (struct interaction *));
1843 examine.iacts[0] = interaction_create (NULL);
1845 examine.exclude = MV_ANY;
1846 examine.histogram = false;
1847 examine.npplot = false;
1848 examine.boxplot = false;
1850 examine.dict = dataset_dict (ds);
1852 /* Accept an optional, completely pointless "/VARIABLES=" */
1853 lex_match (lexer, T_SLASH);
1854 if (lex_match_id (lexer, "VARIABLES"))
1856 if (! lex_force_match (lexer, T_EQUALS) )
1860 if (!parse_variables_const (lexer, examine.dict,
1861 &examine.dep_vars, &examine.n_dep_vars,
1862 PV_NO_DUPLICATE | PV_NUMERIC))
1865 if (lex_match (lexer, T_BY))
1867 struct interaction *iact = NULL;
1870 iact = parse_interaction (lexer, &examine);
1875 pool_nrealloc (examine.pool, iacts_mem,
1877 sizeof (*iacts_mem));
1879 iacts_mem[examine.n_iacts - 1] = iact;
1886 while (lex_token (lexer) != T_ENDCMD)
1888 lex_match (lexer, T_SLASH);
1890 if (lex_match_id (lexer, "STATISTICS"))
1892 lex_match (lexer, T_EQUALS);
1894 while (lex_token (lexer) != T_ENDCMD
1895 && lex_token (lexer) != T_SLASH)
1897 if (lex_match_id (lexer, "DESCRIPTIVES"))
1899 examine.descriptives = true;
1901 else if (lex_match_id (lexer, "EXTREME"))
1904 if (lex_match (lexer, T_LPAREN))
1906 extr = lex_integer (lexer);
1910 msg (MW, _("%s may not be negative. Using default value (%g)."), "EXTREME", 5.0);
1915 if (! lex_force_match (lexer, T_RPAREN))
1918 examine.disp_extremes = extr;
1920 else if (lex_match_id (lexer, "NONE"))
1923 else if (lex_match (lexer, T_ALL))
1925 if (examine.disp_extremes == 0)
1926 examine.disp_extremes = 5;
1930 lex_error (lexer, NULL);
1935 else if (lex_match_id (lexer, "PERCENTILES"))
1937 percentiles_seen = true;
1938 if (lex_match (lexer, T_LPAREN))
1940 while (lex_is_number (lexer))
1942 double p = lex_number (lexer);
1944 if ( p <= 0 || p >= 100.0)
1947 _("Percentiles must lie in the range (0, 100)"));
1951 examine.n_percentiles++;
1953 xrealloc (examine.ptiles,
1954 sizeof (*examine.ptiles) *
1955 examine.n_percentiles);
1957 examine.ptiles[examine.n_percentiles - 1] = p;
1960 lex_match (lexer, T_COMMA);
1962 if (!lex_force_match (lexer, T_RPAREN))
1966 lex_match (lexer, T_EQUALS);
1968 while (lex_token (lexer) != T_ENDCMD
1969 && lex_token (lexer) != T_SLASH)
1971 if (lex_match_id (lexer, "HAVERAGE"))
1973 examine.pc_alg = PC_HAVERAGE;
1975 else if (lex_match_id (lexer, "WAVERAGE"))
1977 examine.pc_alg = PC_WAVERAGE;
1979 else if (lex_match_id (lexer, "ROUND"))
1981 examine.pc_alg = PC_ROUND;
1983 else if (lex_match_id (lexer, "EMPIRICAL"))
1985 examine.pc_alg = PC_EMPIRICAL;
1987 else if (lex_match_id (lexer, "AEMPIRICAL"))
1989 examine.pc_alg = PC_AEMPIRICAL;
1991 else if (lex_match_id (lexer, "NONE"))
1993 examine.pc_alg = PC_NONE;
1997 lex_error (lexer, NULL);
2002 else if (lex_match_id (lexer, "TOTAL"))
2006 else if (lex_match_id (lexer, "NOTOTAL"))
2008 nototals_seen = true;
2010 else if (lex_match_id (lexer, "MISSING"))
2012 lex_match (lexer, T_EQUALS);
2014 while (lex_token (lexer) != T_ENDCMD
2015 && lex_token (lexer) != T_SLASH)
2017 if (lex_match_id (lexer, "LISTWISE"))
2019 examine.missing_pw = false;
2021 else if (lex_match_id (lexer, "PAIRWISE"))
2023 examine.missing_pw = true;
2025 else if (lex_match_id (lexer, "EXCLUDE"))
2027 examine.exclude = MV_ANY;
2029 else if (lex_match_id (lexer, "INCLUDE"))
2031 examine.exclude = MV_SYSTEM;
2035 lex_error (lexer, NULL);
2040 else if (lex_match_id (lexer, "COMPARE"))
2042 lex_match (lexer, T_EQUALS);
2043 if (lex_match_id (lexer, "VARIABLES"))
2045 examine.boxplot_mode = BP_VARIABLES;
2047 else if (lex_match_id (lexer, "GROUPS"))
2049 examine.boxplot_mode = BP_GROUPS;
2053 lex_error (lexer, NULL);
2057 else if (lex_match_id (lexer, "PLOT"))
2059 lex_match (lexer, T_EQUALS);
2061 while (lex_token (lexer) != T_ENDCMD
2062 && lex_token (lexer) != T_SLASH)
2064 if (lex_match_id (lexer, "BOXPLOT"))
2066 examine.boxplot = true;
2068 else if (lex_match_id (lexer, "NPPLOT"))
2070 examine.npplot = true;
2072 else if (lex_match_id (lexer, "HISTOGRAM"))
2074 examine.histogram = true;
2076 else if (lex_match_id (lexer, "NONE"))
2078 examine.histogram = false;
2079 examine.npplot = false;
2080 examine.boxplot = false;
2082 else if (lex_match (lexer, T_ALL))
2084 examine.histogram = true;
2085 examine.npplot = true;
2086 examine.boxplot = true;
2090 lex_error (lexer, NULL);
2093 lex_match (lexer, T_COMMA);
2096 else if (lex_match_id (lexer, "CINTERVAL"))
2098 if ( !lex_force_num (lexer))
2101 examine.conf = lex_number (lexer);
2104 else if (lex_match_id (lexer, "ID"))
2106 lex_match (lexer, T_EQUALS);
2108 examine.id_var = parse_variable_const (lexer, examine.dict);
2112 lex_error (lexer, NULL);
2117 if ( totals_seen && nototals_seen)
2119 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
2123 /* If totals have been requested or if there are no factors
2124 in this analysis, then the totals need to be included. */
2125 if ( !nototals_seen || examine.n_iacts == 1)
2127 examine.iacts = &iacts_mem[0];
2132 examine.iacts = &iacts_mem[1];
2136 if (examine.disp_extremes > 0)
2138 examine.calc_extremes = examine.disp_extremes;
2139 examine.casenumbers = true;
2142 if (examine.boxplot)
2144 examine.casenumbers = true;
2148 if (examine.descriptives && examine.calc_extremes == 0)
2150 /* Descriptives always displays the max and min */
2151 examine.calc_extremes = 1;
2154 if (percentiles_seen && examine.n_percentiles == 0)
2156 examine.n_percentiles = 7;
2157 examine.ptiles = xcalloc (examine.n_percentiles,
2158 sizeof (*examine.ptiles));
2160 examine.ptiles[0] = 5;
2161 examine.ptiles[1] = 10;
2162 examine.ptiles[2] = 25;
2163 examine.ptiles[3] = 50;
2164 examine.ptiles[4] = 75;
2165 examine.ptiles[5] = 90;
2166 examine.ptiles[6] = 95;
2169 assert (examine.calc_extremes >= examine.disp_extremes);
2171 struct casegrouper *grouper;
2172 struct casereader *group;
2175 grouper = casegrouper_create_splits (proc_open (ds), examine.dict);
2176 while (casegrouper_get_next_group (grouper, &group))
2177 run_examine (&examine, group);
2178 ok = casegrouper_destroy (grouper);
2179 ok = proc_commit (ds) && ok;
2182 caseproto_unref (examine.ex_proto);
2184 for (i = 0; i < examine.n_iacts; ++i)
2185 interaction_destroy (examine.iacts[i]);
2187 free (examine.ptiles);
2188 free (examine.dep_vars);
2189 pool_destroy (examine.pool);
2194 caseproto_unref (examine.ex_proto);
2195 for (i = 0; i < examine.n_iacts; ++i)
2196 interaction_destroy (examine.iacts[i]);
2197 free (examine.dep_vars);
2198 free (examine.ptiles);
2199 pool_destroy (examine.pool);