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 */
191 xxx0 (const struct interaction *iact)
195 const union value **prev_val = xcalloc (iact->n_vars, sizeof (*prev_val));
197 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
198 prev_val[ivar_idx] = NULL;
204 xxx1 (const struct interaction *iact, const struct ccase *c, const union value **prev_val)
209 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
211 const struct variable *ivar = iact->vars[ivar_idx];
212 const int width = var_get_width (ivar);
213 const union value *val = case_data (c, ivar);
215 if (prev_val[ivar_idx])
216 if (! value_equal (prev_val[ivar_idx], val, width))
223 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
225 const struct variable *ivar = iact->vars[ivar_idx];
226 const union value *val = case_data (c, ivar);
228 prev_val[ivar_idx] = val;
235 show_boxplot_grouped (const struct examine *cmd, int iact_idx)
239 const struct interaction *iact = cmd->iacts[iact_idx];
240 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
242 for (v = 0; v < cmd->n_dep_vars; ++v)
244 double y_min = DBL_MAX;
245 double y_max = -DBL_MAX;
247 struct boxplot *boxplot;
249 ds_init_empty (&title);
251 if (iact->n_vars > 0)
254 ds_init_empty (&istr);
255 interaction_to_string (iact, &istr);
256 ds_put_format (&title, _("Boxplot of %s vs. %s"),
257 var_to_string (cmd->dep_vars[v]),
262 ds_put_format (&title, _("Boxplot of %s"), var_to_string (cmd->dep_vars[v]));
264 for (grp = 0; grp < n_cats; ++grp)
266 const struct exploratory_stats *es =
267 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
269 if ( y_min > es[v].minimum)
270 y_min = es[v].minimum;
272 if ( y_max < es[v].maximum)
273 y_max = es[v].maximum;
276 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
280 for (grp = 0; grp < n_cats; ++grp)
285 const struct ccase *c =
286 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
288 const struct exploratory_stats *es =
289 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
291 ds_init_empty (&label);
292 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
294 const struct variable *ivar = iact->vars[ivar_idx];
295 const union value *val = case_data (c, ivar);
297 ds_put_cstr (&label, var_to_string (ivar));
298 ds_put_cstr (&label, " = ");
299 var_append_value_name (ivar, val, &label);
300 ds_put_cstr (&label, "; ");
303 boxplot_add_box (boxplot, es[v].box_whisker, ds_cstr (&label));
308 boxplot_submit (boxplot);
313 show_boxplot_variabled (const struct examine *cmd, int iact_idx)
316 const struct interaction *iact = cmd->iacts[iact_idx];
317 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
319 for (grp = 0; grp < n_cats; ++grp)
321 struct boxplot *boxplot;
323 double y_min = DBL_MAX;
324 double y_max = -DBL_MAX;
326 const struct ccase *c =
327 categoricals_get_case_by_category_real (cmd->cats, iact_idx, grp);
330 ds_init_empty (&title);
332 for (v = 0; v < cmd->n_dep_vars; ++v)
334 const struct exploratory_stats *es =
335 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
337 if ( y_min > es[v].minimum)
338 y_min = es[v].minimum;
340 if ( y_max < es[v].maximum)
341 y_max = es[v].maximum;
344 if ( iact->n_vars == 0)
345 ds_put_format (&title, _("Boxplot"));
350 ds_init_empty (&label);
351 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
353 const struct variable *ivar = iact->vars[ivar_idx];
354 const union value *val = case_data (c, ivar);
356 ds_put_cstr (&label, var_to_string (ivar));
357 ds_put_cstr (&label, " = ");
358 var_append_value_name (ivar, val, &label);
359 ds_put_cstr (&label, "; ");
362 ds_put_format (&title, _("Boxplot of %s"),
368 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
372 for (v = 0; v < cmd->n_dep_vars; ++v)
374 const struct exploratory_stats *es =
375 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
377 boxplot_add_box (boxplot, es[v].box_whisker,
378 var_to_string (cmd->dep_vars[v]));
381 boxplot_submit (boxplot);
387 show_npplot (const struct examine *cmd, int iact_idx)
389 const struct interaction *iact = cmd->iacts[iact_idx];
390 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
394 for (v = 0; v < cmd->n_dep_vars; ++v)
397 for (grp = 0; grp < n_cats; ++grp)
399 struct chart_item *npp, *dnpp;
400 struct casereader *reader;
404 const struct ccase *c =
405 categoricals_get_case_by_category_real (cmd->cats,
408 const struct exploratory_stats *es =
409 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
412 ds_init_cstr (&label,
413 var_to_string (cmd->dep_vars[v]));
415 if ( iact->n_vars > 0)
417 ds_put_cstr (&label, " (");
418 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
420 const struct variable *ivar = iact->vars[ivar_idx];
421 const union value *val = case_data (c, ivar);
423 ds_put_cstr (&label, var_to_string (ivar));
424 ds_put_cstr (&label, " = ");
425 var_append_value_name (ivar, val, &label);
426 ds_put_cstr (&label, "; ");
429 ds_put_cstr (&label, ")");
433 reader = casewriter_make_reader (np->writer);
436 npp = np_plot_create (np, reader, ds_cstr (&label));
437 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
439 if (npp == NULL || dnpp == NULL)
441 msg (MW, _("Not creating NP plot because data set is empty."));
442 chart_item_unref (npp);
443 chart_item_unref (dnpp);
447 chart_item_submit (npp);
448 chart_item_submit (dnpp);
450 casereader_destroy (reader);
459 show_histogram (const struct examine *cmd, int iact_idx)
461 const struct interaction *iact = cmd->iacts[iact_idx];
462 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
466 for (v = 0; v < cmd->n_dep_vars; ++v)
469 for (grp = 0; grp < n_cats; ++grp)
473 const struct ccase *c =
474 categoricals_get_case_by_category_real (cmd->cats,
477 const struct exploratory_stats *es =
478 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
481 ds_init_cstr (&label,
482 var_to_string (cmd->dep_vars[v]));
484 if ( iact->n_vars > 0)
486 ds_put_cstr (&label, " (");
487 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
489 const struct variable *ivar = iact->vars[ivar_idx];
490 const union value *val = case_data (c, ivar);
492 ds_put_cstr (&label, var_to_string (ivar));
493 ds_put_cstr (&label, " = ");
494 var_append_value_name (ivar, val, &label);
495 ds_put_cstr (&label, "; ");
498 ds_put_cstr (&label, ")");
502 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
505 ( histogram_chart_create (es[v].histogram->gsl_hist,
506 ds_cstr (&label), n, mean,
516 percentiles_report (const struct examine *cmd, int iact_idx)
518 const struct interaction *iact = cmd->iacts[iact_idx];
520 const int heading_columns = 1 + iact->n_vars + 1;
521 const int heading_rows = 2;
524 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
526 const int rows_per_cat = 2;
527 const int rows_per_var = n_cats * rows_per_cat;
529 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
530 const int nc = heading_columns + cmd->n_percentiles;
532 t = tab_create (nc, nr);
533 tab_title (t, _("Percentiles"));
535 tab_headers (t, heading_columns, 0, heading_rows, 0);
537 /* Internal Vertical lines */
538 tab_box (t, -1, -1, -1, TAL_1,
539 heading_columns, 0, nc - 1, nr - 1);
542 tab_box (t, TAL_2, TAL_2, -1, -1,
543 0, 0, nc - 1, nr - 1);
545 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
546 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
548 tab_joint_text (t, heading_columns, 0,
550 TAT_TITLE | TAB_CENTER,
554 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
557 for (i = 0; i < cmd->n_percentiles; ++i)
559 tab_text_format (t, heading_columns + i, 1,
560 TAT_TITLE | TAB_CENTER,
561 _("%g"), cmd->ptiles[i]);
564 for (i = 0; i < iact->n_vars; ++i)
569 var_to_string (iact->vars[i])
577 tab_vline (t, TAL_1, heading_columns - 1, heading_rows, nr - 1);
579 for (v = 0; v < cmd->n_dep_vars; ++v)
581 const union value **prev_vals = xxx0 (iact);
585 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
588 0, heading_rows + v * rows_per_var,
589 TAT_TITLE | TAB_LEFT,
590 var_to_string (cmd->dep_vars[v])
593 for (i = 0; i < n_cats; ++i)
595 const struct ccase *c =
596 categoricals_get_case_by_category_real (cmd->cats,
599 const struct exploratory_stats *ess =
600 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
602 const struct exploratory_stats *es = ess + v;
604 int diff_idx = xxx1 (iact, c, prev_vals);
609 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
611 const struct variable *ivar = iact->vars[ivar_idx];
612 const union value *val = case_data (c, ivar);
614 if (( diff_idx != -1 && diff_idx <= ivar_idx)
618 ds_init_empty (&str);
619 var_append_value_name (ivar, val, &str);
623 heading_rows + v * rows_per_var + i * rows_per_cat,
624 TAT_TITLE | TAB_LEFT,
632 if ( diff_idx != -1 && diff_idx < iact->n_vars)
634 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
635 heading_rows + v * rows_per_var + i * rows_per_cat
639 tab_text (t, heading_columns - 1,
640 heading_rows + v * rows_per_var + i * rows_per_cat,
641 TAT_TITLE | TAB_LEFT,
642 gettext (ptile_alg_desc [cmd->pc_alg]));
644 tukey_hinges_calculate (es->hinges, hinges);
646 for (p = 0; p < cmd->n_percentiles; ++p)
648 tab_double (t, heading_columns + p,
649 heading_rows + v * rows_per_var + i * rows_per_cat,
651 percentile_calculate (es->percentiles[p], cmd->pc_alg),
654 if (cmd->ptiles[p] == 25.0)
656 tab_double (t, heading_columns + p,
657 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
662 else if (cmd->ptiles[p] == 50.0)
664 tab_double (t, heading_columns + p,
665 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
670 else if (cmd->ptiles[p] == 75.0)
672 tab_double (t, heading_columns + p,
673 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
681 tab_text (t, heading_columns - 1,
682 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
683 TAT_TITLE | TAB_LEFT,
684 _("Tukey's Hinges"));
695 descriptives_report (const struct examine *cmd, int iact_idx)
697 const struct interaction *iact = cmd->iacts[iact_idx];
699 const int heading_columns = 1 + iact->n_vars + 2;
700 const int heading_rows = 1;
703 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
705 const int rows_per_cat = 13;
706 const int rows_per_var = n_cats * rows_per_cat;
708 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
709 const int nc = 2 + heading_columns;
711 t = tab_create (nc, nr);
712 tab_title (t, _("Descriptives"));
714 tab_headers (t, heading_columns, 0, heading_rows, 0);
716 /* Internal Vertical lines */
717 tab_box (t, -1, -1, -1, TAL_1,
718 heading_columns, 0, nc - 1, nr - 1);
721 tab_box (t, TAL_2, TAL_2, -1, -1,
722 0, 0, nc - 1, nr - 1);
724 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
725 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
728 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
731 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
734 for (i = 0; i < iact->n_vars; ++i)
739 var_to_string (iact->vars[i])
743 for (v = 0; v < cmd->n_dep_vars; ++v)
745 const union value **prev_val = xxx0 (iact);
749 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
752 0, heading_rows + v * rows_per_var,
753 TAT_TITLE | TAB_LEFT,
754 var_to_string (cmd->dep_vars[v])
757 for (i = 0; i < n_cats; ++i)
759 const struct ccase *c =
760 categoricals_get_case_by_category_real (cmd->cats,
763 const struct exploratory_stats *ess =
764 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
766 const struct exploratory_stats *es = ess + v;
768 const int diff_idx = xxx1 (iact, c, prev_val);
770 double m0, m1, m2, m3, m4;
773 moments_calculate (es->mom, &m0, &m1, &m2, &m3, &m4);
775 tval = gsl_cdf_tdist_Qinv ((1.0 - cmd->conf) / 2.0, m0 - 1.0);
777 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
779 const struct variable *ivar = iact->vars[ivar_idx];
780 const union value *val = case_data (c, ivar);
782 if (( diff_idx != -1 && diff_idx <= ivar_idx)
786 ds_init_empty (&str);
787 var_append_value_name (ivar, val, &str);
791 heading_rows + v * rows_per_var + i * rows_per_cat,
792 TAT_TITLE | TAB_LEFT,
800 if ( diff_idx != -1 && diff_idx < iact->n_vars)
802 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
803 heading_rows + v * rows_per_var + i * rows_per_cat
809 heading_rows + v * rows_per_var + i * rows_per_cat,
815 1 + iact->n_vars + 2,
816 heading_rows + v * rows_per_var + i * rows_per_cat,
820 1 + iact->n_vars + 3,
821 heading_rows + v * rows_per_var + i * rows_per_cat,
822 0, calc_semean (m2, m0), 0);
826 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
828 _("%g%% Confidence Interval for Mean"),
833 1 + iact->n_vars + 1,
834 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
840 1 + iact->n_vars + 2,
841 heading_rows + v * rows_per_var + i * rows_per_cat + 1,
842 0, m1 - tval * calc_semean (m2, m0), 0);
846 1 + iact->n_vars + 1,
847 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
853 1 + iact->n_vars + 2,
854 heading_rows + v * rows_per_var + i * rows_per_cat + 2,
855 0, m1 + tval * calc_semean (m2, m0), 0);
860 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
866 1 + iact->n_vars + 2,
867 heading_rows + v * rows_per_var + i * rows_per_cat + 3,
869 trimmed_mean_calculate (es->trimmed_mean),
874 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
880 1 + iact->n_vars + 2,
881 heading_rows + v * rows_per_var + i * rows_per_cat + 4,
883 percentile_calculate (es->quartiles[1], cmd->pc_alg),
889 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
895 1 + iact->n_vars + 2,
896 heading_rows + v * rows_per_var + i * rows_per_cat + 5,
901 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
907 1 + iact->n_vars + 2,
908 heading_rows + v * rows_per_var + i * rows_per_cat + 6,
913 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
919 1 + iact->n_vars + 2,
920 heading_rows + v * rows_per_var + i * rows_per_cat + 7,
927 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
933 1 + iact->n_vars + 2,
934 heading_rows + v * rows_per_var + i * rows_per_cat + 8,
941 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
947 1 + iact->n_vars + 2,
948 heading_rows + v * rows_per_var + i * rows_per_cat + 9,
950 es->maxima[0].val - es->minima[0].val,
955 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
957 _("Interquartile Range")
962 1 + iact->n_vars + 2,
963 heading_rows + v * rows_per_var + i * rows_per_cat + 10,
965 percentile_calculate (es->quartiles[2], cmd->pc_alg) -
966 percentile_calculate (es->quartiles[0], cmd->pc_alg),
974 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
980 1 + iact->n_vars + 2,
981 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
985 1 + iact->n_vars + 3,
986 heading_rows + v * rows_per_var + i * rows_per_cat + 11,
987 0, calc_seskew (m0), 0);
991 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
997 1 + iact->n_vars + 2,
998 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1002 1 + iact->n_vars + 3,
1003 heading_rows + v * rows_per_var + i * rows_per_cat + 12,
1004 0, calc_sekurt (m0), 0);
1014 extremes_report (const struct examine *cmd, int iact_idx)
1016 const struct interaction *iact = cmd->iacts[iact_idx];
1018 const int heading_columns = 1 + iact->n_vars + 2;
1019 const int heading_rows = 1;
1020 struct tab_table *t;
1022 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1024 const int rows_per_cat = 2 * cmd->disp_extremes;
1025 const int rows_per_var = n_cats * rows_per_cat;
1027 const int nr = heading_rows + cmd->n_dep_vars * rows_per_var;
1028 const int nc = 2 + heading_columns;
1030 t = tab_create (nc, nr);
1031 tab_title (t, _("Extreme Values"));
1033 tab_headers (t, heading_columns, 0, heading_rows, 0);
1035 /* Internal Vertical lines */
1036 tab_box (t, -1, -1, -1, TAL_1,
1037 heading_columns, 0, nc - 1, nr - 1);
1039 /* External Frame */
1040 tab_box (t, TAL_2, TAL_2, -1, -1,
1041 0, 0, nc - 1, nr - 1);
1043 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1044 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1048 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1049 var_to_string (cmd->id_var));
1051 tab_text (t, heading_columns, 0, TAB_CENTER | TAT_TITLE,
1054 tab_text (t, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE,
1057 for (i = 0; i < iact->n_vars; ++i)
1062 var_to_string (iact->vars[i])
1066 for (v = 0; v < cmd->n_dep_vars; ++v)
1068 const union value **prev_val = xxx0 (iact);
1072 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * rows_per_var);
1075 0, heading_rows + v * rows_per_var,
1077 var_to_string (cmd->dep_vars[v])
1080 for (i = 0; i < n_cats; ++i)
1083 const struct ccase *c =
1084 categoricals_get_case_by_category_real (cmd->cats, iact_idx, i);
1086 const struct exploratory_stats *ess =
1087 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1089 const struct exploratory_stats *es = ess + v;
1091 int diff_idx = xxx1 (iact, c, prev_val);
1093 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1095 const struct variable *ivar = iact->vars[ivar_idx];
1096 const union value *val = case_data (c, ivar);
1098 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1102 ds_init_empty (&str);
1103 var_append_value_name (ivar, val, &str);
1107 heading_rows + v * rows_per_var + i * rows_per_cat,
1108 TAT_TITLE | TAB_LEFT,
1116 if ( diff_idx != -1 && diff_idx < iact->n_vars)
1118 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1119 heading_rows + v * rows_per_var + i * rows_per_cat
1124 heading_columns - 2,
1125 heading_rows + v * rows_per_var + i * rows_per_cat,
1130 tab_hline (t, TAL_1, heading_columns - 2, nc - 1,
1131 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes
1135 heading_columns - 2,
1136 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes,
1140 for (e = 0 ; e < cmd->disp_extremes; ++e)
1143 heading_columns - 1,
1144 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1149 /* The casenumber */
1152 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1154 es->maxima[e].identity,
1159 heading_columns + 1,
1160 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1168 heading_columns - 1,
1169 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1174 /* The casenumber */
1177 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1179 es->minima[e].identity,
1183 heading_columns + 1,
1184 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1198 summary_report (const struct examine *cmd, int iact_idx)
1200 const struct interaction *iact = cmd->iacts[iact_idx];
1202 const int heading_columns = 1 + iact->n_vars;
1203 const int heading_rows = 3;
1204 struct tab_table *t;
1206 const struct fmt_spec *wfmt = cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
1208 size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
1210 const int nr = heading_rows + n_cats * cmd->n_dep_vars;
1211 const int nc = 6 + heading_columns;
1213 t = tab_create (nc, nr);
1214 tab_title (t, _("Case Processing Summary"));
1216 tab_headers (t, heading_columns, 0, heading_rows, 0);
1218 /* Internal Vertical lines */
1219 tab_box (t, -1, -1, -1, TAL_1,
1220 heading_columns, 0, nc - 1, nr - 1);
1222 /* External Frame */
1223 tab_box (t, TAL_2, TAL_2, -1, -1,
1224 0, 0, nc - 1, nr - 1);
1226 tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
1227 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
1229 tab_joint_text (t, heading_columns, 0,
1230 nc - 1, 0, TAB_CENTER | TAT_TITLE, _("Cases"));
1233 heading_columns + 1, 1,
1234 TAB_CENTER | TAT_TITLE, _("Valid"));
1237 heading_columns + 2, 1,
1238 heading_columns + 3, 1,
1239 TAB_CENTER | TAT_TITLE, _("Missing"));
1242 heading_columns + 4, 1,
1243 heading_columns + 5, 1,
1244 TAB_CENTER | TAT_TITLE, _("Total"));
1246 for (i = 0; i < 3; ++i)
1248 tab_text (t, heading_columns + i * 2, 2, TAB_CENTER | TAT_TITLE,
1250 tab_text (t, heading_columns + i * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1254 for (i = 0; i < iact->n_vars; ++i)
1259 var_to_string (iact->vars[i])
1264 for (v = 0; v < cmd->n_dep_vars; ++v)
1267 const union value **prev_values = xxx0 (iact);
1270 tab_hline (t, TAL_1, 0, nc - 1, heading_rows + v * n_cats);
1273 0, heading_rows + n_cats * v,
1275 var_to_string (cmd->dep_vars[v])
1279 for (i = 0; i < n_cats; ++i)
1282 const struct exploratory_stats *es;
1284 const struct ccase *c =
1285 categoricals_get_case_by_category_real (cmd->cats,
1289 int diff_idx = xxx1 (iact, c, prev_values);
1291 if ( diff_idx != -1 && diff_idx < iact->n_vars - 1)
1292 tab_hline (t, TAL_1, 1 + diff_idx, nc - 1,
1293 heading_rows + n_cats * v + i );
1295 for (ivar_idx = 0; ivar_idx < iact->n_vars; ++ivar_idx)
1297 const struct variable *ivar = iact->vars[ivar_idx];
1298 const union value *val = case_data (c, ivar);
1300 if (( diff_idx != -1 && diff_idx <= ivar_idx)
1304 ds_init_empty (&str);
1305 var_append_value_name (ivar, val, &str);
1308 1 + ivar_idx, heading_rows + n_cats * v + i,
1309 TAT_TITLE | TAB_LEFT,
1319 es = categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, i);
1322 total = es[v].missing + es[v].non_missing;
1324 heading_columns + 0,
1325 heading_rows + n_cats * v + i,
1332 heading_columns + 1,
1333 heading_rows + n_cats * v + i,
1336 100.0 * es[v].non_missing / total
1341 heading_columns + 2,
1342 heading_rows + n_cats * v + i,
1348 heading_columns + 3,
1349 heading_rows + n_cats * v + i,
1352 100.0 * es[v].missing / total
1355 heading_columns + 4,
1356 heading_rows + n_cats * v + i,
1361 /* This can only be 100% can't it? */
1363 heading_columns + 5,
1364 heading_rows + n_cats * v + i,
1367 100.0 * (es[v].missing + es[v].non_missing)/ total
1373 tab_hline (t, TAL_1, heading_columns, nc - 1, 1);
1374 tab_hline (t, TAL_1, heading_columns, nc - 1, 2);
1380 /* Match a variable.
1381 If the match succeeds, the variable will be placed in VAR.
1382 Returns true if successful */
1384 lex_match_variable (struct lexer *lexer,
1385 const struct dictionary *dict, const struct variable **var)
1387 if (lex_token (lexer) != T_ID)
1391 *var = parse_variable_const (lexer, dict);
1398 /* Attempt to parse an interaction from LEXER */
1399 static struct interaction *
1400 parse_interaction (struct lexer *lexer, struct examine *ex)
1402 const struct variable *v = NULL;
1403 struct interaction *iact = NULL;
1405 if ( lex_match_variable (lexer, ex->dict, &v))
1407 iact = interaction_create (v);
1409 while (lex_match (lexer, T_BY))
1411 if (!lex_match_variable (lexer, ex->dict, &v))
1413 interaction_destroy (iact);
1416 interaction_add_variable (iact, v);
1418 lex_match (lexer, T_COMMA);
1426 create_n (const void *aux1, void *aux2 UNUSED)
1430 const struct examine *examine = aux1;
1431 struct exploratory_stats *es = pool_calloc (examine->pool, examine->n_dep_vars, sizeof (*es));
1432 struct subcase ordering;
1433 subcase_init (&ordering, 0, 0, SC_ASCEND);
1435 for (v = 0; v < examine->n_dep_vars; v++)
1437 es[v].sorted_writer = sort_create_writer (&ordering, examine->ex_proto);
1438 es[v].sorted_reader = NULL;
1440 es[v].mom = moments_create (MOMENT_KURTOSIS);
1441 es[v].cmin = DBL_MAX;
1443 es[v].maximum = -DBL_MAX;
1444 es[v].minimum = DBL_MAX;
1447 subcase_destroy (&ordering);
1452 update_n (const void *aux1, void *aux2 UNUSED, void *user_data,
1453 const struct ccase *c, double weight)
1456 const struct examine *examine = aux1;
1457 struct exploratory_stats *es = user_data;
1459 for (v = 0; v < examine->n_dep_vars; v++)
1461 const struct variable *var = examine->dep_vars[v];
1462 const double x = case_data (c, var)->f;
1464 if (var_is_value_missing (var, case_data (c, var), examine->exclude))
1466 es[v].missing += weight;
1470 struct ccase *outcase = case_create (examine->ex_proto);
1472 if (x > es[v].maximum)
1475 if (x < es[v].minimum)
1478 es[v].non_missing += weight;
1480 moments_pass_one (es[v].mom, x, weight);
1482 /* Save the value and the casenumber to the writer */
1483 case_data_rw_idx (outcase, EX_VAL)->f = x;
1484 if ( examine->id_idx != -1)
1485 case_data_rw_idx (outcase, EX_ID)->f = case_data_idx (c, examine->id_idx)->f;
1487 case_data_rw_idx (outcase, EX_WT)->f = weight;
1491 if (es[v].cmin > weight)
1492 es[v].cmin = weight;
1494 casewriter_write (es[v].sorted_writer, outcase);
1499 calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data)
1502 const struct examine *examine = aux1;
1503 struct exploratory_stats *es = user_data;
1505 for (v = 0; v < examine->n_dep_vars; v++)
1508 casenumber imin = 0;
1509 double imax = es[v].cc;
1510 struct casereader *reader;
1512 casenumber total_cases;
1514 if (examine->histogram)
1517 histogram_create (10, es[v].minimum, es[v].maximum);
1520 es[v].sorted_reader = casewriter_make_reader (es[v].sorted_writer);
1521 total_cases = casereader_count_cases (es[v].sorted_reader);
1522 es[v].sorted_writer = NULL;
1524 es[v].maxima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].maxima));
1525 es[v].minima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].minima));
1527 for (reader = casereader_clone (es[v].sorted_reader);
1528 (c = casereader_read (reader)) != NULL; case_unref (c))
1530 const double val = case_data_idx (c, EX_VAL)->f;
1531 const double wt = case_data_idx (c, EX_WT)->f; /* FIXME: What about fractional weights ??? */
1533 moments_pass_two (es[v].mom, val, wt);
1535 if (es[v].histogram)
1536 histogram_add (es[v].histogram, val, wt);
1538 if (imin < examine->calc_extremes)
1541 for (x = imin; x < examine->calc_extremes; ++x)
1543 struct extremity *min = &es[v].minima[x];
1545 min->identity = case_data_idx (c, EX_ID)->f;
1551 if (imax < examine->calc_extremes)
1555 for (x = imax; x < imax + wt; ++x)
1557 struct extremity *max;
1559 if (x >= examine->calc_extremes)
1562 max = &es[v].maxima[x];
1564 max->identity = case_data_idx (c, EX_ID)->f;
1568 casereader_destroy (reader);
1570 if (examine->calc_extremes > 0)
1572 assert (es[v].minima[0].val == es[v].minimum);
1573 assert (es[v].maxima[0].val == es[v].maximum);
1577 const int n_os = 5 + examine->n_percentiles;
1578 struct order_stats **os ;
1579 es[v].percentiles = pool_calloc (examine->pool, examine->n_percentiles, sizeof (*es[v].percentiles));
1581 es[v].trimmed_mean = trimmed_mean_create (es[v].cc, 0.05);
1583 os = xcalloc (n_os, sizeof *os);
1584 os[0] = &es[v].trimmed_mean->parent;
1586 es[v].quartiles[0] = percentile_create (0.25, es[v].cc);
1587 es[v].quartiles[1] = percentile_create (0.5, es[v].cc);
1588 es[v].quartiles[2] = percentile_create (0.75, es[v].cc);
1590 os[1] = &es[v].quartiles[0]->parent;
1591 os[2] = &es[v].quartiles[1]->parent;
1592 os[3] = &es[v].quartiles[2]->parent;
1594 es[v].hinges = tukey_hinges_create (es[v].cc, es[v].cmin);
1595 os[4] = &es[v].hinges->parent;
1597 for (i = 0; i < examine->n_percentiles; ++i)
1599 es[v].percentiles[i] = percentile_create (examine->ptiles[i] / 100.00, es[v].cc);
1600 os[5 + i] = &es[v].percentiles[i]->parent;
1603 order_stats_accumulate_idx (os, n_os,
1604 casereader_clone (es[v].sorted_reader),
1610 if (examine->boxplot)
1612 struct order_stats *os;
1614 es[v].box_whisker = box_whisker_create (es[v].hinges,
1617 os = &es[v].box_whisker->parent;
1618 order_stats_accumulate_idx (&os, 1,
1619 casereader_clone (es[v].sorted_reader),
1623 if (examine->npplot)
1625 double n, mean, var;
1626 struct order_stats *os;
1628 moments_calculate (es[v].mom, &n, &mean, &var, NULL, NULL);
1630 es[v].np = np_create (n, mean, var);
1632 os = &es[v].np->parent;
1634 order_stats_accumulate_idx (&os, 1,
1635 casereader_clone (es[v].sorted_reader),
1643 cleanup_exploratory_stats (struct examine *cmd)
1646 for (i = 0; i < cmd->n_iacts; ++i)
1649 const size_t n_cats = categoricals_n_count (cmd->cats, i);
1651 for (v = 0; v < cmd->n_dep_vars; ++v)
1654 for (grp = 0; grp < n_cats; ++grp)
1657 const struct exploratory_stats *es =
1658 categoricals_get_user_data_by_category_real (cmd->cats, i, grp);
1660 struct order_stats *os = es[v].hinges;
1661 struct statistic *stat = &os->parent;
1662 stat->destroy (stat);
1664 for (q = 0; q < 3 ; q++)
1666 os = es[v].quartiles[q];
1668 stat->destroy (stat);
1671 for (q = 0; q < cmd->n_percentiles ; q++)
1673 os = es[v].percentiles[q];
1675 stat->destroy (stat);
1678 os = es[v].trimmed_mean;
1680 stat->destroy (stat);
1686 stat->destroy (stat);
1689 os = es[v].histogram;
1693 stat->destroy (stat);
1696 moments_destroy (es[v].mom);
1698 casereader_destroy (es[v].sorted_reader);
1706 run_examine (struct examine *cmd, struct casereader *input)
1710 struct casereader *reader;
1712 struct payload payload;
1713 payload.create = create_n;
1714 payload.update = update_n;
1715 payload.destroy = calculate_n;
1717 cmd->wv = dict_get_weight (cmd->dict);
1721 = categoricals_create (cmd->iacts, cmd->n_iacts,
1722 cmd->wv, cmd->exclude);
1724 categoricals_set_payload (cmd->cats, &payload, cmd, NULL);
1726 if (cmd->casenumbers)
1728 struct ccase *c = casereader_peek (input, 0);
1731 cmd->id_idx = var_get_case_index (cmd->id_var);
1734 cmd->id_idx = case_get_value_cnt (c);
1735 input = casereader_create_arithmetic_sequence (input, 1.0, 1.0);
1741 /* FIXME: Filter out missing factor variables */
1743 /* Remove cases on a listwise basis if requested */
1744 if ( cmd->missing_pw == false)
1745 input = casereader_create_filter_missing (input,
1752 for (reader = input;
1753 (c = casereader_read (reader)) != NULL; case_unref (c))
1755 categoricals_update (cmd->cats, c);
1757 casereader_destroy (reader);
1758 categoricals_done (cmd->cats);
1760 for (i = 0; i < cmd->n_iacts; ++i)
1762 summary_report (cmd, i);
1764 if (cmd->disp_extremes > 0)
1765 extremes_report (cmd, i);
1767 if (cmd->n_percentiles > 0)
1768 percentiles_report (cmd, i);
1772 switch (cmd->boxplot_mode)
1775 show_boxplot_grouped (cmd, i);
1778 show_boxplot_variabled (cmd, i);
1787 show_histogram (cmd, i);
1790 show_npplot (cmd, i);
1792 if (cmd->descriptives)
1793 descriptives_report (cmd, i);
1796 cleanup_exploratory_stats (cmd);
1797 categoricals_destroy (cmd->cats);
1802 cmd_examine (struct lexer *lexer, struct dataset *ds)
1805 bool nototals_seen = false;
1806 bool totals_seen = false;
1808 struct interaction **iacts_mem = NULL;
1809 struct examine examine;
1810 bool percentiles_seen = false;
1812 examine.casenumbers = false;
1813 examine.missing_pw = false;
1814 examine.disp_extremes = 0;
1815 examine.calc_extremes = 0;
1816 examine.descriptives = false;
1817 examine.conf = 0.95;
1818 examine.pc_alg = PC_HAVERAGE;
1819 examine.ptiles = NULL;
1820 examine.n_percentiles = 0;
1822 examine.boxplot_mode = BP_GROUPS;
1824 examine.ex_proto = caseproto_create ();
1825 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */
1826 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* id */
1827 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */
1829 examine.pool = pool_create ();
1831 /* Allocate space for the first interaction.
1832 This is interaction is an empty one (for the totals).
1833 If no totals are requested, we will simply ignore this
1836 examine.n_iacts = 1;
1837 examine.iacts = iacts_mem = pool_zalloc (examine.pool, sizeof (struct interaction *));
1838 examine.iacts[0] = interaction_create (NULL);
1840 examine.exclude = MV_ANY;
1841 examine.histogram = false;
1842 examine.npplot = false;
1843 examine.boxplot = false;
1845 examine.dict = dataset_dict (ds);
1847 /* Accept an optional, completely pointless "/VARIABLES=" */
1848 lex_match (lexer, T_SLASH);
1849 if (lex_match_id (lexer, "VARIABLES"))
1851 if (! lex_force_match (lexer, T_EQUALS) )
1855 if (!parse_variables_const (lexer, examine.dict,
1856 &examine.dep_vars, &examine.n_dep_vars,
1857 PV_NO_DUPLICATE | PV_NUMERIC))
1860 if (lex_match (lexer, T_BY))
1862 struct interaction *iact = NULL;
1865 iact = parse_interaction (lexer, &examine);
1870 pool_nrealloc (examine.pool, iacts_mem,
1872 sizeof (*iacts_mem));
1874 iacts_mem[examine.n_iacts - 1] = iact;
1881 while (lex_token (lexer) != T_ENDCMD)
1883 lex_match (lexer, T_SLASH);
1885 if (lex_match_id (lexer, "STATISTICS"))
1887 lex_match (lexer, T_EQUALS);
1889 while (lex_token (lexer) != T_ENDCMD
1890 && lex_token (lexer) != T_SLASH)
1892 if (lex_match_id (lexer, "DESCRIPTIVES"))
1894 examine.descriptives = true;
1896 else if (lex_match_id (lexer, "EXTREME"))
1899 if (lex_match (lexer, T_LPAREN))
1901 extr = lex_integer (lexer);
1905 msg (MW, _("%s may not be negative. Using default value (%g)."), "EXTREME", 5.0);
1910 if (! lex_force_match (lexer, T_RPAREN))
1913 examine.disp_extremes = extr;
1915 else if (lex_match_id (lexer, "NONE"))
1918 else if (lex_match (lexer, T_ALL))
1920 if (examine.disp_extremes == 0)
1921 examine.disp_extremes = 5;
1925 lex_error (lexer, NULL);
1930 else if (lex_match_id (lexer, "PERCENTILES"))
1932 percentiles_seen = true;
1933 if (lex_match (lexer, T_LPAREN))
1935 while (lex_is_number (lexer))
1937 double p = lex_number (lexer);
1939 if ( p <= 0 || p >= 100.0)
1942 _("Percentiles must lie in the range (0, 100)"));
1946 examine.n_percentiles++;
1948 xrealloc (examine.ptiles,
1949 sizeof (*examine.ptiles) *
1950 examine.n_percentiles);
1952 examine.ptiles[examine.n_percentiles - 1] = p;
1955 lex_match (lexer, T_COMMA);
1957 if (!lex_force_match (lexer, T_RPAREN))
1961 lex_match (lexer, T_EQUALS);
1963 while (lex_token (lexer) != T_ENDCMD
1964 && lex_token (lexer) != T_SLASH)
1966 if (lex_match_id (lexer, "HAVERAGE"))
1968 examine.pc_alg = PC_HAVERAGE;
1970 else if (lex_match_id (lexer, "WAVERAGE"))
1972 examine.pc_alg = PC_WAVERAGE;
1974 else if (lex_match_id (lexer, "ROUND"))
1976 examine.pc_alg = PC_ROUND;
1978 else if (lex_match_id (lexer, "EMPIRICAL"))
1980 examine.pc_alg = PC_EMPIRICAL;
1982 else if (lex_match_id (lexer, "AEMPIRICAL"))
1984 examine.pc_alg = PC_AEMPIRICAL;
1986 else if (lex_match_id (lexer, "NONE"))
1988 examine.pc_alg = PC_NONE;
1992 lex_error (lexer, NULL);
1997 else if (lex_match_id (lexer, "TOTAL"))
2001 else if (lex_match_id (lexer, "NOTOTAL"))
2003 nototals_seen = true;
2005 else if (lex_match_id (lexer, "MISSING"))
2007 lex_match (lexer, T_EQUALS);
2009 while (lex_token (lexer) != T_ENDCMD
2010 && lex_token (lexer) != T_SLASH)
2012 if (lex_match_id (lexer, "LISTWISE"))
2014 examine.missing_pw = false;
2016 else if (lex_match_id (lexer, "PAIRWISE"))
2018 examine.missing_pw = true;
2020 else if (lex_match_id (lexer, "EXCLUDE"))
2022 examine.exclude = MV_ANY;
2024 else if (lex_match_id (lexer, "INCLUDE"))
2026 examine.exclude = MV_SYSTEM;
2030 lex_error (lexer, NULL);
2035 else if (lex_match_id (lexer, "COMPARE"))
2037 lex_match (lexer, T_EQUALS);
2038 if (lex_match_id (lexer, "VARIABLES"))
2040 examine.boxplot_mode = BP_VARIABLES;
2042 else if (lex_match_id (lexer, "GROUPS"))
2044 examine.boxplot_mode = BP_GROUPS;
2048 lex_error (lexer, NULL);
2052 else if (lex_match_id (lexer, "PLOT"))
2054 lex_match (lexer, T_EQUALS);
2056 while (lex_token (lexer) != T_ENDCMD
2057 && lex_token (lexer) != T_SLASH)
2059 if (lex_match_id (lexer, "BOXPLOT"))
2061 examine.boxplot = true;
2063 else if (lex_match_id (lexer, "NPPLOT"))
2065 examine.npplot = true;
2067 else if (lex_match_id (lexer, "HISTOGRAM"))
2069 examine.histogram = true;
2071 else if (lex_match_id (lexer, "NONE"))
2073 examine.histogram = false;
2074 examine.npplot = false;
2075 examine.boxplot = false;
2077 else if (lex_match (lexer, T_ALL))
2079 examine.histogram = true;
2080 examine.npplot = true;
2081 examine.boxplot = true;
2085 lex_error (lexer, NULL);
2088 lex_match (lexer, T_COMMA);
2091 else if (lex_match_id (lexer, "CINTERVAL"))
2093 if ( !lex_force_num (lexer))
2096 examine.conf = lex_number (lexer);
2099 else if (lex_match_id (lexer, "ID"))
2101 lex_match (lexer, T_EQUALS);
2103 examine.id_var = parse_variable_const (lexer, examine.dict);
2107 lex_error (lexer, NULL);
2112 if ( totals_seen && nototals_seen)
2114 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
2118 /* If totals have been requested or if there are no factors
2119 in this analysis, then the totals need to be included. */
2120 if ( !nototals_seen || examine.n_iacts == 1)
2122 examine.iacts = &iacts_mem[0];
2127 examine.iacts = &iacts_mem[1];
2131 if (examine.disp_extremes > 0)
2133 examine.calc_extremes = examine.disp_extremes;
2134 examine.casenumbers = true;
2137 if (examine.boxplot)
2139 examine.casenumbers = true;
2143 if (examine.descriptives && examine.calc_extremes == 0)
2145 /* Descriptives always displays the max and min */
2146 examine.calc_extremes = 1;
2149 if (percentiles_seen && examine.n_percentiles == 0)
2151 examine.n_percentiles = 7;
2152 examine.ptiles = xcalloc (examine.n_percentiles,
2153 sizeof (*examine.ptiles));
2155 examine.ptiles[0] = 5;
2156 examine.ptiles[1] = 10;
2157 examine.ptiles[2] = 25;
2158 examine.ptiles[3] = 50;
2159 examine.ptiles[4] = 75;
2160 examine.ptiles[5] = 90;
2161 examine.ptiles[6] = 95;
2164 assert (examine.calc_extremes >= examine.disp_extremes);
2166 struct casegrouper *grouper;
2167 struct casereader *group;
2170 grouper = casegrouper_create_splits (proc_open (ds), examine.dict);
2171 while (casegrouper_get_next_group (grouper, &group))
2172 run_examine (&examine, group);
2173 ok = casegrouper_destroy (grouper);
2174 ok = proc_commit (ds) && ok;
2177 caseproto_unref (examine.ex_proto);
2179 for (i = 0; i < examine.n_iacts; ++i)
2180 interaction_destroy (examine.iacts[i]);
2182 free (examine.ptiles);
2183 free (examine.dep_vars);
2184 pool_destroy (examine.pool);
2189 caseproto_unref (examine.ex_proto);
2190 for (i = 0; i < examine.n_iacts; ++i)
2191 interaction_destroy (examine.iacts[i]);
2192 free (examine.dep_vars);
2193 free (examine.ptiles);
2194 pool_destroy (examine.pool);