1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <gsl/gsl_cdf.h>
20 #include <libpspp/message.h>
25 #include <math/sort.h>
26 #include <math/order-stats.h>
27 #include <math/percentiles.h>
28 #include <math/tukey-hinges.h>
29 #include <math/box-whisker.h>
30 #include <math/trimmed-mean.h>
31 #include <math/extrema.h>
33 #include <data/case.h>
34 #include <data/casegrouper.h>
35 #include <data/casereader.h>
36 #include <data/casewriter.h>
37 #include <data/dictionary.h>
38 #include <data/procedure.h>
39 #include <data/subcase.h>
40 #include <data/value-labels.h>
41 #include <data/variable.h>
42 #include <language/command.h>
43 #include <language/dictionary/split-file.h>
44 #include <language/lexer/lexer.h>
45 #include <libpspp/compiler.h>
46 #include <libpspp/hash.h>
47 #include <libpspp/message.h>
48 #include <libpspp/misc.h>
49 #include <libpspp/str.h>
50 #include <math/moments.h>
51 #include <output/chart-item.h>
52 #include <output/charts/boxplot.h>
53 #include <output/charts/np-plot.h>
54 #include <output/tab.h>
60 #define _(msgid) gettext (msgid)
61 #define N_(msgid) msgid
64 #include <output/charts/plot-hist.h>
65 #include <math/histogram.h>
72 missing=miss:pairwise/!listwise,
74 incl:include/!exclude;
75 +compare=cmp:variables/!groups;
78 +plot[plt_]=stemleaf,boxplot,npplot,:spreadlevel(*d:n),histogram,all,none;
80 +statistics[st_]=descriptives,:extreme(*d:n),all,none.
88 static struct cmd_examine cmd;
90 static const struct variable **dependent_vars;
91 static size_t n_dependent_vars;
95 static subc_list_double percentile_list;
96 static enum pc_alg percentile_algorithm;
100 struct moments1 *moments;
102 struct percentile **ptl;
105 struct tukey_hinges *tukey_hinges;
106 struct box_whisker *box_whisker;
107 struct trimmed_mean *trimmed_mean;
108 struct histogram *histogram;
111 /* Three quartiles indexing into PTL */
112 struct percentile **quartiles;
114 /* A reader sorted in ASCENDING order */
115 struct casereader *up_reader;
117 /* The minimum value of all the weights */
120 /* Sum of all weights, including those for missing values */
123 /* Sum of weights of non_missing values */
136 struct extrema *minima;
137 struct extrema *maxima;
144 union value value[2];
146 /* An array of factor metrics, one for each variable */
147 struct factor_metrics *metrics;
152 /* We need to make a list of this structure */
155 /* The independent variable */
156 const struct variable const* indep_var[2];
158 /* A list of results for this factor */
159 struct ll_list result_list ;
164 factor_destroy (struct xfactor *fctr)
166 struct ll *ll = ll_head (&fctr->result_list);
167 while (ll != ll_null (&fctr->result_list))
170 struct factor_result *result =
171 ll_data (ll, struct factor_result, ll);
174 for (v = 0; v < n_dependent_vars; ++v)
177 moments1_destroy (result->metrics[v].moments);
178 extrema_destroy (result->metrics[v].minima);
179 extrema_destroy (result->metrics[v].maxima);
180 statistic_destroy (&result->metrics[v].trimmed_mean->parent.parent);
181 statistic_destroy (&result->metrics[v].tukey_hinges->parent.parent);
182 statistic_destroy (&result->metrics[v].box_whisker->parent.parent);
183 statistic_destroy (&result->metrics[v].histogram->parent);
184 for (i = 0 ; i < result->metrics[v].n_ptiles; ++i)
185 statistic_destroy (&result->metrics[v].ptl[i]->parent.parent);
186 free (result->metrics[v].ptl);
187 free (result->metrics[v].quartiles);
188 casereader_destroy (result->metrics[v].up_reader);
191 for (i = 0; i < 2; i++)
192 if (fctr->indep_var[i])
193 value_destroy (&result->value[i],
194 var_get_width (fctr->indep_var[i]));
195 free (result->metrics);
201 static struct xfactor level0_factor;
202 static struct ll_list factor_list;
204 /* Parse the clause specifying the factors */
205 static int examine_parse_independent_vars (struct lexer *lexer,
206 const struct dictionary *dict,
207 struct cmd_examine *cmd);
209 /* Output functions */
210 static void show_summary (const struct variable **dependent_var, int n_dep_var,
211 const struct dictionary *dict,
212 const struct xfactor *f);
215 static void show_descriptives (const struct variable **dependent_var,
217 const struct xfactor *f);
220 static void show_percentiles (const struct variable **dependent_var,
222 const struct xfactor *f);
225 static void show_extremes (const struct variable **dependent_var,
227 const struct xfactor *f);
232 /* Per Split function */
233 static void run_examine (struct cmd_examine *, struct casereader *,
236 static void output_examine (const struct dictionary *dict);
239 void factor_calc (const struct ccase *c, int case_no,
240 double weight, bool case_missing);
243 /* Represent a factor as a string, so it can be
244 printed in a human readable fashion */
245 static void factor_to_string (const struct xfactor *fctr,
246 const struct factor_result *result,
249 /* Represent a factor as a string, so it can be
250 printed in a human readable fashion,
251 but sacrificing some readablility for the sake of brevity */
253 factor_to_string_concise (const struct xfactor *fctr,
254 const struct factor_result *result,
260 /* Categories of missing values to exclude. */
261 static enum mv_class exclude_values;
264 cmd_examine (struct lexer *lexer, struct dataset *ds)
266 struct casegrouper *grouper;
267 struct casereader *group;
270 subc_list_double_create (&percentile_list);
271 percentile_algorithm = PC_HAVERAGE;
273 ll_init (&factor_list);
275 if ( !parse_examine (lexer, ds, &cmd, NULL) )
277 subc_list_double_destroy (&percentile_list);
281 /* If /MISSING=INCLUDE is set, then user missing values are ignored */
282 exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
284 if ( cmd.st_n == SYSMIS )
287 if ( ! cmd.sbc_cinterval)
288 cmd.n_cinterval[0] = 95.0;
290 /* If descriptives have been requested, make sure the
291 quartiles are calculated */
292 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
294 subc_list_double_push (&percentile_list, 25);
295 subc_list_double_push (&percentile_list, 50);
296 subc_list_double_push (&percentile_list, 75);
299 grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
301 while (casegrouper_get_next_group (grouper, &group))
303 struct casereader *reader =
304 casereader_create_arithmetic_sequence (group, 1, 1);
306 run_examine (&cmd, reader, ds);
309 ok = casegrouper_destroy (grouper);
310 ok = proc_commit (ds) && ok;
312 if ( dependent_vars )
313 free (dependent_vars);
315 subc_list_double_destroy (&percentile_list);
317 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
324 show_npplot (const struct variable **dependent_var,
326 const struct xfactor *fctr)
330 for (v = 0; v < n_dep_var; ++v)
333 for (ll = ll_head (&fctr->result_list);
334 ll != ll_null (&fctr->result_list);
338 const struct factor_result *result =
339 ll_data (ll, struct factor_result, ll);
340 struct chart_item *npp, *dnpp;
341 struct casereader *reader;
344 ds_init_empty (&label);
345 ds_put_format (&label, "%s ", var_get_name (dependent_var[v]));
346 factor_to_string (fctr, result, &label);
348 np = result->metrics[v].np;
349 reader = casewriter_make_reader (np->writer);
350 npp = np_plot_create (np, reader, ds_cstr (&label));
351 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
355 if (npp == NULL || dnpp == NULL)
357 msg (MW, _("Not creating NP plot because data set is empty."));
358 chart_item_unref (npp);
359 chart_item_unref (dnpp);
363 chart_item_submit (npp);
364 chart_item_submit (dnpp);
367 statistic_destroy (&np->parent.parent);
368 casereader_destroy (reader);
375 show_histogram (const struct variable **dependent_var,
377 const struct xfactor *fctr)
381 for (v = 0; v < n_dep_var; ++v)
384 for (ll = ll_head (&fctr->result_list);
385 ll != ll_null (&fctr->result_list);
389 const struct factor_result *result =
390 ll_data (ll, struct factor_result, ll);
391 struct histogram *histogram;
394 histogram = result->metrics[v].histogram;
395 if (histogram == NULL)
397 /* Probably all values are SYSMIS. */
401 ds_init_empty (&str);
402 ds_put_format (&str, "%s ", var_get_name (dependent_var[v]));
404 factor_to_string (fctr, result, &str);
406 moments1_calculate (result->metrics[v].moments,
407 &n, &mean, &var, NULL, NULL);
408 chart_item_submit (histogram_chart_create (histogram->gsl_hist,
409 ds_cstr (&str), n, mean,
420 show_boxplot_groups (const struct variable **dependent_var,
422 const struct xfactor *fctr)
426 for (v = 0; v < n_dep_var; ++v)
428 const struct factor_result *result;
429 struct boxplot *boxplot;
430 double y_min = DBL_MAX;
431 double y_max = -DBL_MAX;
434 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
436 struct factor_metrics *metrics = &result->metrics[v];
437 const struct ll_list *max_list = extrema_list (metrics->maxima);
438 const struct ll_list *min_list = extrema_list (metrics->minima);
439 const struct extremum *max, *min;
441 if ( ll_is_empty (max_list))
443 msg (MW, _("Not creating plot because data set is empty."));
447 max = ll_data (ll_head(max_list), struct extremum, ll);
448 min = ll_data (ll_head (min_list), struct extremum, ll);
450 y_max = MAX (y_max, max->value);
451 y_min = MIN (y_min, min->value);
454 if (fctr->indep_var[0])
455 title = xasprintf (_("Boxplot of %s vs. %s"),
456 var_to_string (dependent_var[v]),
457 var_to_string (fctr->indep_var[0]));
459 title = xasprintf (_("Boxplot of %s"),
460 var_to_string (dependent_var[v]));
461 boxplot = boxplot_create (y_min, y_max, title);
464 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
466 struct factor_metrics *metrics = &result->metrics[v];
467 struct string str = DS_EMPTY_INITIALIZER;
468 factor_to_string_concise (fctr, result, &str);
469 boxplot_add_box (boxplot, metrics->box_whisker, ds_cstr (&str));
470 metrics->box_whisker = NULL;
474 boxplot_submit (boxplot);
481 show_boxplot_variables (const struct variable **dependent_var,
483 const struct xfactor *fctr
487 const struct factor_result *result;
490 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
493 double y_min = DBL_MAX;
494 double y_max = -DBL_MAX;
495 struct boxplot *boxplot;
497 for (v = 0; v < n_dep_var; ++v)
499 const struct factor_metrics *metrics = &result->metrics[v];
500 const struct ll *max_ll = ll_head (extrema_list (metrics->maxima));
501 const struct ll *min_ll = ll_head (extrema_list (metrics->minima));
502 const struct extremum *max = ll_data (max_ll, struct extremum, ll);
503 const struct extremum *min = ll_data (min_ll, struct extremum, ll);
505 y_max = MAX (y_max, max->value);
506 y_min = MIN (y_min, min->value);
509 ds_init_empty (&title);
510 factor_to_string (fctr, result, &title);
511 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
514 for (v = 0; v < n_dep_var; ++v)
516 struct factor_metrics *metrics = &result->metrics[v];
517 boxplot_add_box (boxplot, metrics->box_whisker,
518 var_get_name (dependent_var[v]));
519 metrics->box_whisker = NULL;
522 boxplot_submit (boxplot);
527 /* Show all the appropriate tables */
529 output_examine (const struct dictionary *dict)
533 show_summary (dependent_vars, n_dependent_vars, dict, &level0_factor);
535 if ( cmd.a_statistics[XMN_ST_EXTREME] )
536 show_extremes (dependent_vars, n_dependent_vars, &level0_factor);
538 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
539 show_descriptives (dependent_vars, n_dependent_vars, &level0_factor);
541 if ( cmd.sbc_percentiles)
542 show_percentiles (dependent_vars, n_dependent_vars, &level0_factor);
546 if (cmd.a_plot[XMN_PLT_BOXPLOT])
547 show_boxplot_groups (dependent_vars, n_dependent_vars, &level0_factor);
549 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
550 show_histogram (dependent_vars, n_dependent_vars, &level0_factor);
552 if (cmd.a_plot[XMN_PLT_NPPLOT])
553 show_npplot (dependent_vars, n_dependent_vars, &level0_factor);
556 for (ll = ll_head (&factor_list);
557 ll != ll_null (&factor_list); ll = ll_next (ll))
559 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
560 show_summary (dependent_vars, n_dependent_vars, dict, factor);
562 if ( cmd.a_statistics[XMN_ST_EXTREME] )
563 show_extremes (dependent_vars, n_dependent_vars, factor);
565 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
566 show_descriptives (dependent_vars, n_dependent_vars, factor);
568 if ( cmd.sbc_percentiles)
569 show_percentiles (dependent_vars, n_dependent_vars, factor);
571 if (cmd.a_plot[XMN_PLT_BOXPLOT])
573 if (cmd.cmp == XMN_GROUPS)
574 show_boxplot_groups (dependent_vars, n_dependent_vars, factor);
575 else if (cmd.cmp == XMN_VARIABLES)
576 show_boxplot_variables (dependent_vars, n_dependent_vars, factor);
579 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
580 show_histogram (dependent_vars, n_dependent_vars, factor);
582 if (cmd.a_plot[XMN_PLT_NPPLOT])
583 show_npplot (dependent_vars, n_dependent_vars, factor);
587 /* Parse the PERCENTILES subcommand */
589 xmn_custom_percentiles (struct lexer *lexer, struct dataset *ds UNUSED,
590 struct cmd_examine *p UNUSED, void *aux UNUSED)
592 lex_match (lexer, '=');
594 lex_match (lexer, '(');
596 while ( lex_is_number (lexer) )
598 subc_list_double_push (&percentile_list, lex_number (lexer));
602 lex_match (lexer, ',') ;
604 lex_match (lexer, ')');
606 lex_match (lexer, '=');
608 if ( lex_match_id (lexer, "HAVERAGE"))
609 percentile_algorithm = PC_HAVERAGE;
611 else if ( lex_match_id (lexer, "WAVERAGE"))
612 percentile_algorithm = PC_WAVERAGE;
614 else if ( lex_match_id (lexer, "ROUND"))
615 percentile_algorithm = PC_ROUND;
617 else if ( lex_match_id (lexer, "EMPIRICAL"))
618 percentile_algorithm = PC_EMPIRICAL;
620 else if ( lex_match_id (lexer, "AEMPIRICAL"))
621 percentile_algorithm = PC_AEMPIRICAL;
623 else if ( lex_match_id (lexer, "NONE"))
624 percentile_algorithm = PC_NONE;
627 if ( 0 == subc_list_double_count (&percentile_list))
629 subc_list_double_push (&percentile_list, 5);
630 subc_list_double_push (&percentile_list, 10);
631 subc_list_double_push (&percentile_list, 25);
632 subc_list_double_push (&percentile_list, 50);
633 subc_list_double_push (&percentile_list, 75);
634 subc_list_double_push (&percentile_list, 90);
635 subc_list_double_push (&percentile_list, 95);
641 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
643 xmn_custom_total (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
644 struct cmd_examine *p, void *aux UNUSED)
646 if ( p->sbc_nototal )
648 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
656 xmn_custom_nototal (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
657 struct cmd_examine *p, void *aux UNUSED)
661 msg (SE, _("%s and %s are mutually exclusive"), "TOTAL", "NOTOTAL");
670 /* Parser for the variables sub command
671 Returns 1 on success */
673 xmn_custom_variables (struct lexer *lexer, struct dataset *ds,
674 struct cmd_examine *cmd,
677 const struct dictionary *dict = dataset_dict (ds);
678 lex_match (lexer, '=');
680 if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
681 && lex_token (lexer) != T_ALL)
686 if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars,
687 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
689 free (dependent_vars);
693 assert (n_dependent_vars);
696 if ( lex_match (lexer, T_BY))
699 success = examine_parse_independent_vars (lexer, dict, cmd);
702 free (dependent_vars);
712 /* Parse the clause specifying the factors */
714 examine_parse_independent_vars (struct lexer *lexer,
715 const struct dictionary *dict,
716 struct cmd_examine *cmd)
719 struct xfactor *sf = xmalloc (sizeof *sf);
721 ll_init (&sf->result_list);
723 if ( (lex_token (lexer) != T_ID ||
724 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
725 && lex_token (lexer) != T_ALL)
731 sf->indep_var[0] = parse_variable (lexer, dict);
732 sf->indep_var[1] = NULL;
734 if ( lex_token (lexer) == T_BY )
736 lex_match (lexer, T_BY);
738 if ( (lex_token (lexer) != T_ID ||
739 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
740 && lex_token (lexer) != T_ALL)
746 sf->indep_var[1] = parse_variable (lexer, dict);
748 ll_push_tail (&factor_list, &sf->ll);
751 ll_push_tail (&factor_list, &sf->ll);
753 lex_match (lexer, ',');
755 if ( lex_token (lexer) == '.' || lex_token (lexer) == '/' )
758 success = examine_parse_independent_vars (lexer, dict, cmd);
767 examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
768 const struct dictionary *dict, struct xfactor *factor)
771 const struct variable *wv = dict_get_weight (dict);
774 struct factor_result *result = xzalloc (sizeof (*result));
777 for (i = 0; i < 2; i++)
778 if (factor->indep_var[i])
779 value_init (&result->value[i], var_get_width (factor->indep_var[i]));
781 result->metrics = xcalloc (n_dependent_vars, sizeof (*result->metrics));
783 if ( cmd->a_statistics[XMN_ST_EXTREME] )
784 n_extrema = cmd->st_n;
787 c = casereader_peek (reader, 0);
791 for (i = 0; i < 2; i++)
792 if (factor->indep_var[i])
793 value_copy (&result->value[i], case_data (c, factor->indep_var[i]),
794 var_get_width (factor->indep_var[i]));
798 for (v = 0; v < n_dependent_vars; ++v)
800 struct casewriter *writer;
801 struct casereader *input = casereader_clone (reader);
803 result->metrics[v].moments = moments1_create (MOMENT_KURTOSIS);
804 result->metrics[v].minima = extrema_create (n_extrema, EXTREME_MINIMA);
805 result->metrics[v].maxima = extrema_create (n_extrema, EXTREME_MAXIMA);
806 result->metrics[v].cmin = DBL_MAX;
808 if (cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
809 cmd->a_plot[XMN_PLT_BOXPLOT] ||
810 cmd->a_plot[XMN_PLT_NPPLOT] ||
811 cmd->sbc_percentiles)
813 /* In this case, we need to sort the data, so we create a sorting
815 struct subcase up_ordering;
816 subcase_init_var (&up_ordering, dependent_vars[v], SC_ASCEND);
817 writer = sort_create_writer (&up_ordering,
818 casereader_get_proto (reader));
819 subcase_destroy (&up_ordering);
823 /* but in this case, sorting is unnecessary, so an ordinary
824 casewriter is sufficient */
826 autopaging_writer_create (casereader_get_proto (reader));
830 /* Sort or just iterate, whilst calculating moments etc */
831 while ((c = casereader_read (input)) != NULL)
833 int n_vals = caseproto_get_n_widths (casereader_get_proto (reader));
834 const casenumber loc = case_data_idx (c, n_vals - 1)->f;
836 const double weight = wv ? case_data (c, wv)->f : 1.0;
837 const union value *value = case_data (c, dependent_vars[v]);
839 if (weight != SYSMIS)
840 minimize (&result->metrics[v].cmin, weight);
842 moments1_add (result->metrics[v].moments,
846 result->metrics[v].n += weight;
848 if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
849 result->metrics[v].n_valid += weight;
851 extrema_add (result->metrics[v].maxima,
856 extrema_add (result->metrics[v].minima,
861 casewriter_write (writer, c);
863 casereader_destroy (input);
864 result->metrics[v].up_reader = casewriter_make_reader (writer);
867 /* If percentiles or descriptives have been requested, then a
868 second pass through the data (which has now been sorted)
870 if ( cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
871 cmd->a_plot[XMN_PLT_BOXPLOT] ||
872 cmd->a_plot[XMN_PLT_NPPLOT] ||
873 cmd->sbc_percentiles)
875 for (v = 0; v < n_dependent_vars; ++v)
879 struct order_stats **os ;
880 struct factor_metrics *metric = &result->metrics[v];
882 metric->n_ptiles = percentile_list.n_data;
884 metric->ptl = xcalloc (metric->n_ptiles, sizeof *metric->ptl);
886 metric->quartiles = xcalloc (3, sizeof (*metric->quartiles));
888 for (i = 0 ; i < metric->n_ptiles; ++i)
890 metric->ptl[i] = percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
892 if ( percentile_list.data[i] == 25)
893 metric->quartiles[0] = metric->ptl[i];
894 else if ( percentile_list.data[i] == 50)
895 metric->quartiles[1] = metric->ptl[i];
896 else if ( percentile_list.data[i] == 75)
897 metric->quartiles[2] = metric->ptl[i];
900 metric->tukey_hinges = tukey_hinges_create (metric->n_valid, metric->cmin);
901 metric->trimmed_mean = trimmed_mean_create (metric->n_valid, 0.05);
903 n_os = metric->n_ptiles + 2;
905 if ( cmd->a_plot[XMN_PLT_NPPLOT] )
907 metric->np = np_create (metric->moments);
911 os = xcalloc (n_os, sizeof *os);
913 for (i = 0 ; i < metric->n_ptiles ; ++i )
915 os[i] = &metric->ptl[i]->parent;
918 os[i] = &metric->tukey_hinges->parent;
919 os[i+1] = &metric->trimmed_mean->parent;
921 if (cmd->a_plot[XMN_PLT_NPPLOT])
922 os[i+2] = &metric->np->parent;
924 order_stats_accumulate (os, n_os,
925 casereader_clone (metric->up_reader),
926 wv, dependent_vars[v], MV_ANY);
931 /* FIXME: Do this in the above loop */
932 if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
935 struct casereader *input = casereader_clone (reader);
937 for (v = 0; v < n_dependent_vars; ++v)
939 const struct extremum *max, *min;
940 struct factor_metrics *metric = &result->metrics[v];
942 const struct ll_list *max_list =
943 extrema_list (result->metrics[v].maxima);
945 const struct ll_list *min_list =
946 extrema_list (result->metrics[v].minima);
948 if ( ll_is_empty (max_list))
950 msg (MW, _("Not creating plot because data set is empty."));
954 assert (! ll_is_empty (min_list));
956 max = (const struct extremum *)
957 ll_data (ll_head(max_list), struct extremum, ll);
959 min = (const struct extremum *)
960 ll_data (ll_head (min_list), struct extremum, ll);
962 metric->histogram = histogram_create (10, min->value, max->value);
965 while ((c = casereader_read (input)) != NULL)
967 const double weight = wv ? case_data (c, wv)->f : 1.0;
969 for (v = 0; v < n_dependent_vars; ++v)
971 struct factor_metrics *metric = &result->metrics[v];
972 if ( metric->histogram)
973 histogram_add (metric->histogram,
974 case_data (c, dependent_vars[v])->f, weight);
978 casereader_destroy (input);
981 /* In this case, a third iteration is required */
982 if (cmd->a_plot[XMN_PLT_BOXPLOT])
984 for (v = 0; v < n_dependent_vars; ++v)
986 struct factor_metrics *metric = &result->metrics[v];
987 int n_vals = caseproto_get_n_widths (casereader_get_proto (
989 struct order_stats *os;
991 metric->box_whisker =
992 box_whisker_create ( metric->tukey_hinges, cmd->v_id, n_vals - 1);
994 os = &metric->box_whisker->parent;
995 order_stats_accumulate ( &os, 1,
996 casereader_clone (metric->up_reader),
997 wv, dependent_vars[v], MV_ANY);
1001 ll_push_tail (&factor->result_list, &result->ll);
1002 casereader_destroy (reader);
1007 run_examine (struct cmd_examine *cmd, struct casereader *input,
1011 const struct dictionary *dict = dataset_dict (ds);
1013 struct casereader *level0 = casereader_clone (input);
1015 c = casereader_peek (input, 0);
1018 casereader_destroy (input);
1022 output_split_file_values (ds, c);
1025 ll_init (&level0_factor.result_list);
1027 examine_group (cmd, level0, 0, dict, &level0_factor);
1029 for (ll = ll_head (&factor_list);
1030 ll != ll_null (&factor_list);
1033 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
1035 struct casereader *group = NULL;
1036 struct casereader *level1;
1037 struct casegrouper *grouper1 = NULL;
1039 level1 = casereader_clone (input);
1040 level1 = sort_execute_1var (level1, factor->indep_var[0]);
1041 grouper1 = casegrouper_create_vars (level1, &factor->indep_var[0], 1);
1043 while (casegrouper_get_next_group (grouper1, &group))
1045 struct casereader *group_copy = casereader_clone (group);
1047 if ( !factor->indep_var[1])
1048 examine_group (cmd, group_copy, 1, dict, factor);
1052 struct casereader *group2 = NULL;
1053 struct casegrouper *grouper2 = NULL;
1055 group_copy = sort_execute_1var (group_copy,
1056 factor->indep_var[1]);
1058 grouper2 = casegrouper_create_vars (group_copy,
1059 &factor->indep_var[1], 1);
1061 while (casegrouper_get_next_group (grouper2, &group2))
1063 examine_group (cmd, group2, 2, dict, factor);
1066 casegrouper_destroy (grouper2);
1069 casereader_destroy (group);
1071 casegrouper_destroy (grouper1);
1074 casereader_destroy (input);
1076 output_examine (dict);
1078 factor_destroy (&level0_factor);
1082 for (ll = ll_head (&factor_list);
1083 ll != ll_null (&factor_list);
1086 struct xfactor *f = ll_data (ll, struct xfactor, ll);
1095 show_summary (const struct variable **dependent_var, int n_dep_var,
1096 const struct dictionary *dict,
1097 const struct xfactor *fctr)
1099 const struct variable *wv = dict_get_weight (dict);
1100 const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
1102 static const char *subtitle[]=
1110 int heading_columns = 1;
1112 const int heading_rows = 3;
1113 struct tab_table *tbl;
1120 if ( fctr->indep_var[0] )
1122 heading_columns = 2;
1124 if ( fctr->indep_var[1] )
1126 heading_columns = 3;
1130 n_rows *= ll_count (&fctr->result_list);
1131 n_rows += heading_rows;
1133 n_cols = heading_columns + 6;
1135 tbl = tab_create (n_cols, n_rows);
1136 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1138 /* Outline the box */
1143 n_cols - 1, n_rows - 1);
1145 /* Vertical lines for the data only */
1150 n_cols - 1, n_rows - 1);
1153 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1154 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
1155 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, heading_rows -1 );
1157 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1160 tab_title (tbl, _("Case Processing Summary"));
1162 tab_joint_text (tbl, heading_columns, 0,
1164 TAB_CENTER | TAT_TITLE,
1167 /* Remove lines ... */
1174 for (j = 0 ; j < 3 ; ++j)
1176 tab_text (tbl, heading_columns + j * 2 , 2, TAB_CENTER | TAT_TITLE,
1179 tab_text (tbl, heading_columns + j * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1182 tab_joint_text (tbl, heading_columns + j * 2 , 1,
1183 heading_columns + j * 2 + 1, 1,
1184 TAB_CENTER | TAT_TITLE,
1187 tab_box (tbl, -1, -1,
1189 heading_columns + j * 2, 1,
1190 heading_columns + j * 2 + 1, 1);
1194 /* Titles for the independent variables */
1195 if ( fctr->indep_var[0] )
1197 tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1198 var_to_string (fctr->indep_var[0]));
1200 if ( fctr->indep_var[1] )
1202 tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1203 var_to_string (fctr->indep_var[1]));
1207 for (v = 0 ; v < n_dep_var ; ++v)
1211 const union value *last_value = NULL;
1214 tab_hline (tbl, TAL_1, 0, n_cols -1 ,
1215 v * ll_count (&fctr->result_list)
1220 v * ll_count (&fctr->result_list) + heading_rows,
1221 TAB_LEFT | TAT_TITLE,
1222 var_to_string (dependent_var[v])
1226 for (ll = ll_head (&fctr->result_list);
1227 ll != ll_null (&fctr->result_list); ll = ll_next (ll))
1230 const struct factor_result *result =
1231 ll_data (ll, struct factor_result, ll);
1233 if ( fctr->indep_var[0] )
1236 if ( last_value == NULL ||
1237 !value_equal (last_value, &result->value[0],
1238 var_get_width (fctr->indep_var[0])))
1242 last_value = &result->value[0];
1243 ds_init_empty (&str);
1245 var_append_value_name (fctr->indep_var[0], &result->value[0],
1250 v * ll_count (&fctr->result_list),
1251 TAB_LEFT | TAT_TITLE,
1256 if ( fctr->indep_var[1] && j > 0)
1257 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1259 v * ll_count (&fctr->result_list));
1262 if ( fctr->indep_var[1])
1266 ds_init_empty (&str);
1268 var_append_value_name (fctr->indep_var[1],
1269 &result->value[1], &str);
1273 v * ll_count (&fctr->result_list),
1274 TAB_LEFT | TAT_TITLE,
1282 moments1_calculate (result->metrics[v].moments,
1283 &n, &result->metrics[v].mean,
1284 &result->metrics[v].variance,
1285 &result->metrics[v].skewness,
1286 &result->metrics[v].kurtosis);
1288 result->metrics[v].se_mean = sqrt (result->metrics[v].variance / n) ;
1291 tab_double (tbl, heading_columns,
1292 heading_rows + j + v * ll_count (&fctr->result_list),
1296 tab_text_format (tbl, heading_columns + 1,
1297 heading_rows + j + v * ll_count (&fctr->result_list),
1299 "%g%%", n * 100.0 / result->metrics[v].n);
1302 tab_double (tbl, heading_columns + 2,
1303 heading_rows + j + v * ll_count (&fctr->result_list),
1305 result->metrics[v].n - n,
1308 tab_text_format (tbl, heading_columns + 3,
1309 heading_rows + j + v * ll_count (&fctr->result_list),
1312 (result->metrics[v].n - n) * 100.0 / result->metrics[v].n
1315 /* Total Valid + Missing */
1316 tab_double (tbl, heading_columns + 4,
1317 heading_rows + j + v * ll_count (&fctr->result_list),
1319 result->metrics[v].n,
1322 tab_text_format (tbl, heading_columns + 5,
1323 heading_rows + j + v * ll_count (&fctr->result_list),
1326 ((result->metrics[v].n) * 100.0
1327 / result->metrics[v].n));
1337 #define DESCRIPTIVE_ROWS 13
1340 show_descriptives (const struct variable **dependent_var,
1342 const struct xfactor *fctr)
1345 int heading_columns = 3;
1347 const int heading_rows = 1;
1348 struct tab_table *tbl;
1355 if ( fctr->indep_var[0] )
1357 heading_columns = 4;
1359 if ( fctr->indep_var[1] )
1361 heading_columns = 5;
1365 n_rows *= ll_count (&fctr->result_list) * DESCRIPTIVE_ROWS;
1366 n_rows += heading_rows;
1368 n_cols = heading_columns + 2;
1370 tbl = tab_create (n_cols, n_rows);
1371 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1373 /* Outline the box */
1378 n_cols - 1, n_rows - 1);
1381 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1382 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1384 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1387 if ( fctr->indep_var[0])
1388 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1390 if ( fctr->indep_var[1])
1391 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1393 for (v = 0 ; v < n_dep_var ; ++v )
1398 const int row_var_start =
1399 v * DESCRIPTIVE_ROWS * ll_count(&fctr->result_list);
1403 heading_rows + row_var_start,
1404 TAB_LEFT | TAT_TITLE,
1405 var_to_string (dependent_var[v])
1408 for (ll = ll_head (&fctr->result_list);
1409 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1411 const struct factor_result *result =
1412 ll_data (ll, struct factor_result, ll);
1415 gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0) / 2.0,
1416 result->metrics[v].n - 1);
1418 if ( i > 0 || v > 0 )
1420 const int left_col = (i == 0) ? 0 : 1;
1421 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1422 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS);
1425 if ( fctr->indep_var[0])
1428 ds_init_empty (&vstr);
1429 var_append_value_name (fctr->indep_var[0],
1430 &result->value[0], &vstr);
1433 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1442 tab_text (tbl, n_cols - 4,
1443 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1447 tab_text_format (tbl, n_cols - 4,
1448 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1450 _("%g%% Confidence Interval for Mean"),
1451 cmd.n_cinterval[0]);
1453 tab_text (tbl, n_cols - 3,
1454 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1458 tab_text (tbl, n_cols - 3,
1459 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1463 tab_text (tbl, n_cols - 4,
1464 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1465 TAB_LEFT, _("5% Trimmed Mean"));
1467 tab_text (tbl, n_cols - 4,
1468 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1472 tab_text (tbl, n_cols - 4,
1473 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1477 tab_text (tbl, n_cols - 4,
1478 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1480 _("Std. Deviation"));
1482 tab_text (tbl, n_cols - 4,
1483 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1487 tab_text (tbl, n_cols - 4,
1488 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1492 tab_text (tbl, n_cols - 4,
1493 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1497 tab_text (tbl, n_cols - 4,
1498 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1500 _("Interquartile Range"));
1503 tab_text (tbl, n_cols - 4,
1504 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1508 tab_text (tbl, n_cols - 4,
1509 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1514 /* Now the statistics ... */
1516 tab_double (tbl, n_cols - 2,
1517 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1519 result->metrics[v].mean,
1522 tab_double (tbl, n_cols - 1,
1523 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1525 result->metrics[v].se_mean,
1529 tab_double (tbl, n_cols - 2,
1530 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1532 result->metrics[v].mean - t *
1533 result->metrics[v].se_mean,
1536 tab_double (tbl, n_cols - 2,
1537 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1539 result->metrics[v].mean + t *
1540 result->metrics[v].se_mean,
1544 tab_double (tbl, n_cols - 2,
1545 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1547 trimmed_mean_calculate (result->metrics[v].trimmed_mean),
1551 tab_double (tbl, n_cols - 2,
1552 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1554 percentile_calculate (result->metrics[v].quartiles[1], percentile_algorithm),
1558 tab_double (tbl, n_cols - 2,
1559 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1561 result->metrics[v].variance,
1564 tab_double (tbl, n_cols - 2,
1565 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1567 sqrt (result->metrics[v].variance),
1570 tab_double (tbl, n_cols - 2,
1571 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1573 percentile_calculate (result->metrics[v].quartiles[2],
1574 percentile_algorithm) -
1575 percentile_calculate (result->metrics[v].quartiles[0],
1576 percentile_algorithm),
1580 tab_double (tbl, n_cols - 2,
1581 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1583 result->metrics[v].skewness,
1586 tab_double (tbl, n_cols - 2,
1587 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1589 result->metrics[v].kurtosis,
1592 tab_double (tbl, n_cols - 1,
1593 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1595 calc_seskew (result->metrics[v].n),
1598 tab_double (tbl, n_cols - 1,
1599 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1601 calc_sekurt (result->metrics[v].n),
1605 struct extremum *minimum, *maximum ;
1607 struct ll *max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1608 struct ll *min_ll = ll_head (extrema_list (result->metrics[v].minima));
1610 maximum = ll_data (max_ll, struct extremum, ll);
1611 minimum = ll_data (min_ll, struct extremum, ll);
1613 tab_double (tbl, n_cols - 2,
1614 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1619 tab_double (tbl, n_cols - 2,
1620 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1625 tab_double (tbl, n_cols - 2,
1626 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1628 maximum->value - minimum->value,
1634 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1636 tab_title (tbl, _("Descriptives"));
1638 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1641 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1650 show_extremes (const struct variable **dependent_var,
1652 const struct xfactor *fctr)
1655 int heading_columns = 3;
1657 const int heading_rows = 1;
1658 struct tab_table *tbl;
1665 if ( fctr->indep_var[0] )
1667 heading_columns = 4;
1669 if ( fctr->indep_var[1] )
1671 heading_columns = 5;
1675 n_rows *= ll_count (&fctr->result_list) * cmd.st_n * 2;
1676 n_rows += heading_rows;
1678 n_cols = heading_columns + 2;
1680 tbl = tab_create (n_cols, n_rows);
1681 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1683 /* Outline the box */
1688 n_cols - 1, n_rows - 1);
1691 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1692 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1693 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1695 if ( fctr->indep_var[0])
1696 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1698 if ( fctr->indep_var[1])
1699 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1701 for (v = 0 ; v < n_dep_var ; ++v )
1705 const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
1709 heading_rows + row_var_start,
1710 TAB_LEFT | TAT_TITLE,
1711 var_to_string (dependent_var[v])
1714 for (ll = ll_head (&fctr->result_list);
1715 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1720 const int row_result_start = i * cmd.st_n * 2;
1722 const struct factor_result *result =
1723 ll_data (ll, struct factor_result, ll);
1726 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1727 heading_rows + row_var_start + row_result_start);
1729 tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
1730 heading_rows + row_var_start + row_result_start + cmd.st_n);
1732 for ( e = 1; e <= cmd.st_n; ++e )
1734 tab_text_format (tbl, n_cols - 3,
1735 heading_rows + row_var_start + row_result_start + e - 1,
1739 tab_text_format (tbl, n_cols - 3,
1740 heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
1746 min_ll = ll_head (extrema_list (result->metrics[v].minima));
1747 for (e = 0; e < cmd.st_n;)
1749 struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
1750 double weight = minimum->weight;
1752 while (weight-- > 0 && e < cmd.st_n)
1754 tab_double (tbl, n_cols - 1,
1755 heading_rows + row_var_start + row_result_start + cmd.st_n + e,
1761 tab_fixed (tbl, n_cols - 2,
1762 heading_rows + row_var_start +
1763 row_result_start + cmd.st_n + e,
1770 min_ll = ll_next (min_ll);
1773 max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1774 for (e = 0; e < cmd.st_n;)
1776 struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
1777 double weight = maximum->weight;
1779 while (weight-- > 0 && e < cmd.st_n)
1781 tab_double (tbl, n_cols - 1,
1782 heading_rows + row_var_start +
1783 row_result_start + e,
1789 tab_fixed (tbl, n_cols - 2,
1790 heading_rows + row_var_start +
1791 row_result_start + e,
1798 max_ll = ll_next (max_ll);
1802 if ( fctr->indep_var[0])
1805 ds_init_empty (&vstr);
1806 var_append_value_name (fctr->indep_var[0],
1807 &result->value[0], &vstr);
1810 heading_rows + row_var_start + row_result_start,
1819 tab_text (tbl, n_cols - 4,
1820 heading_rows + row_var_start + row_result_start,
1824 tab_text (tbl, n_cols - 4,
1825 heading_rows + row_var_start + row_result_start + cmd.st_n,
1831 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1834 tab_title (tbl, _("Extreme Values"));
1837 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1841 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1847 #define PERCENTILE_ROWS 2
1850 show_percentiles (const struct variable **dependent_var,
1852 const struct xfactor *fctr)
1856 int heading_columns = 2;
1858 const int n_percentiles = subc_list_double_count (&percentile_list);
1859 const int heading_rows = 2;
1860 struct tab_table *tbl;
1867 if ( fctr->indep_var[0] )
1869 heading_columns = 3;
1871 if ( fctr->indep_var[1] )
1873 heading_columns = 4;
1877 n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
1878 n_rows += heading_rows;
1880 n_cols = heading_columns + n_percentiles;
1882 tbl = tab_create (n_cols, n_rows);
1883 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1885 /* Outline the box */
1890 n_cols - 1, n_rows - 1);
1893 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1894 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1896 if ( fctr->indep_var[0])
1897 tab_text (tbl, 1, 1, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1899 if ( fctr->indep_var[1])
1900 tab_text (tbl, 2, 1, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1902 for (v = 0 ; v < n_dep_var ; ++v )
1908 const int row_var_start =
1909 v * PERCENTILE_ROWS * ll_count(&fctr->result_list);
1913 heading_rows + row_var_start,
1914 TAB_LEFT | TAT_TITLE,
1915 var_to_string (dependent_var[v])
1918 for (ll = ll_head (&fctr->result_list);
1919 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1922 const struct factor_result *result =
1923 ll_data (ll, struct factor_result, ll);
1925 if ( i > 0 || v > 0 )
1927 const int left_col = (i == 0) ? 0 : 1;
1928 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1929 heading_rows + row_var_start + i * PERCENTILE_ROWS);
1932 if ( fctr->indep_var[0])
1935 ds_init_empty (&vstr);
1936 var_append_value_name (fctr->indep_var[0],
1937 &result->value[0], &vstr);
1940 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1949 tab_text (tbl, n_cols - n_percentiles - 1,
1950 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1952 ptile_alg_desc [percentile_algorithm]);
1955 tab_text (tbl, n_cols - n_percentiles - 1,
1956 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1958 _("Tukey's Hinges"));
1961 tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1);
1963 tukey_hinges_calculate (result->metrics[v].tukey_hinges, hinges);
1965 for (j = 0; j < n_percentiles; ++j)
1967 double hinge = SYSMIS;
1968 tab_double (tbl, n_cols - n_percentiles + j,
1969 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1971 percentile_calculate (result->metrics[v].ptl[j],
1972 percentile_algorithm),
1976 if ( result->metrics[v].ptl[j]->ptile == 0.5)
1978 else if ( result->metrics[v].ptl[j]->ptile == 0.25)
1980 else if ( result->metrics[v].ptl[j]->ptile == 0.75)
1983 if ( hinge != SYSMIS)
1984 tab_double (tbl, n_cols - n_percentiles + j,
1985 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1995 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1997 tab_title (tbl, _("Percentiles"));
2000 for (i = 0 ; i < n_percentiles; ++i )
2002 tab_text_format (tbl, n_cols - n_percentiles + i, 1,
2003 TAB_CENTER | TAT_TITLE,
2005 subc_list_double_at (&percentile_list, i));
2010 tab_joint_text (tbl,
2011 n_cols - n_percentiles, 0,
2013 TAB_CENTER | TAT_TITLE,
2016 /* Vertical lines for the data only */
2020 n_cols - n_percentiles, 1,
2021 n_cols - 1, n_rows - 1);
2023 tab_hline (tbl, TAL_1, n_cols - n_percentiles, n_cols - 1, 1);
2031 factor_to_string_concise (const struct xfactor *fctr,
2032 const struct factor_result *result,
2036 if (fctr->indep_var[0])
2038 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2040 if ( fctr->indep_var[1] )
2042 ds_put_cstr (str, ",");
2044 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2046 ds_put_cstr (str, ")");
2053 factor_to_string (const struct xfactor *fctr,
2054 const struct factor_result *result,
2058 if (fctr->indep_var[0])
2060 ds_put_format (str, "(%s = ", var_get_name (fctr->indep_var[0]));
2062 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2064 if ( fctr->indep_var[1] )
2066 ds_put_cstr (str, ",");
2067 ds_put_format (str, "%s = ", var_get_name (fctr->indep_var[1]));
2069 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2071 ds_put_cstr (str, ")");