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/charts/box-whisker.h>
52 #include <output/charts/np-plot.h>
53 #include <output/manager.h>
54 #include <output/table.h>
60 #define _(msgid) gettext (msgid)
61 #define N_(msgid) msgid
64 #include <output/chart.h>
65 #include <output/charts/plot-hist.h>
66 #include <output/charts/plot-chart.h>
67 #include <math/histogram.h>
74 missing=miss:pairwise/!listwise,
76 incl:include/!exclude;
77 +compare=cmp:variables/!groups;
80 +plot[plt_]=stemleaf,boxplot,npplot,:spreadlevel(*d:n),histogram,all,none;
82 +statistics[st_]=descriptives,:extreme(*d:n),all,none.
90 static struct cmd_examine cmd;
92 static const struct variable **dependent_vars;
93 static size_t n_dependent_vars;
97 static subc_list_double percentile_list;
98 static enum pc_alg percentile_algorithm;
100 struct factor_metrics
102 struct moments1 *moments;
104 struct percentile **ptl;
107 struct statistic *tukey_hinges;
108 struct statistic *box_whisker;
109 struct statistic *trimmed_mean;
110 struct statistic *histogram;
111 struct order_stats *np;
113 /* Three quartiles indexing into PTL */
114 struct percentile **quartiles;
116 /* A reader sorted in ASCENDING order */
117 struct casereader *up_reader;
119 /* The minimum value of all the weights */
122 /* Sum of all weights, including those for missing values */
125 /* Sum of weights of non_missing values */
138 struct extrema *minima;
139 struct extrema *maxima;
146 union value value[2];
148 /* An array of factor metrics, one for each variable */
149 struct factor_metrics *metrics;
154 /* We need to make a list of this structure */
157 /* The independent variable */
158 const struct variable const* indep_var[2];
160 /* A list of results for this factor */
161 struct ll_list result_list ;
166 factor_destroy (struct xfactor *fctr)
168 struct ll *ll = ll_head (&fctr->result_list);
169 while (ll != ll_null (&fctr->result_list))
172 struct factor_result *result =
173 ll_data (ll, struct factor_result, ll);
176 for (v = 0; v < n_dependent_vars; ++v)
179 moments1_destroy (result->metrics[v].moments);
180 extrema_destroy (result->metrics[v].minima);
181 extrema_destroy (result->metrics[v].maxima);
182 statistic_destroy (result->metrics[v].trimmed_mean);
183 statistic_destroy (result->metrics[v].tukey_hinges);
184 statistic_destroy (result->metrics[v].box_whisker);
185 statistic_destroy (result->metrics[v].histogram);
186 for (i = 0 ; i < result->metrics[v].n_ptiles; ++i)
187 statistic_destroy ((struct statistic *) result->metrics[v].ptl[i]);
188 free (result->metrics[v].ptl);
189 free (result->metrics[v].quartiles);
190 casereader_destroy (result->metrics[v].up_reader);
193 for (i = 0; i < 2; i++)
194 if (fctr->indep_var[i])
195 value_destroy (&result->value[i],
196 var_get_width (fctr->indep_var[i]));
197 free (result->metrics);
203 static struct xfactor level0_factor;
204 static struct ll_list factor_list;
206 /* Parse the clause specifying the factors */
207 static int examine_parse_independent_vars (struct lexer *lexer,
208 const struct dictionary *dict,
209 struct cmd_examine *cmd);
211 /* Output functions */
212 static void show_summary (const struct variable **dependent_var, int n_dep_var,
213 const struct dictionary *dict,
214 const struct xfactor *f);
217 static void show_descriptives (const struct variable **dependent_var,
219 const struct xfactor *f);
222 static void show_percentiles (const struct variable **dependent_var,
224 const struct xfactor *f);
227 static void show_extremes (const struct variable **dependent_var,
229 const struct xfactor *f);
234 /* Per Split function */
235 static void run_examine (struct cmd_examine *, struct casereader *,
238 static void output_examine (const struct dictionary *dict);
241 void factor_calc (const struct ccase *c, int case_no,
242 double weight, bool case_missing);
245 /* Represent a factor as a string, so it can be
246 printed in a human readable fashion */
247 static void factor_to_string (const struct xfactor *fctr,
248 const struct factor_result *result,
251 /* Represent a factor as a string, so it can be
252 printed in a human readable fashion,
253 but sacrificing some readablility for the sake of brevity */
255 factor_to_string_concise (const struct xfactor *fctr,
256 const struct factor_result *result,
262 /* Categories of missing values to exclude. */
263 static enum mv_class exclude_values;
266 cmd_examine (struct lexer *lexer, struct dataset *ds)
268 struct casegrouper *grouper;
269 struct casereader *group;
272 subc_list_double_create (&percentile_list);
273 percentile_algorithm = PC_HAVERAGE;
275 ll_init (&factor_list);
277 if ( !parse_examine (lexer, ds, &cmd, NULL) )
279 subc_list_double_destroy (&percentile_list);
283 /* If /MISSING=INCLUDE is set, then user missing values are ignored */
284 exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
286 if ( cmd.st_n == SYSMIS )
289 if ( ! cmd.sbc_cinterval)
290 cmd.n_cinterval[0] = 95.0;
292 /* If descriptives have been requested, make sure the
293 quartiles are calculated */
294 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
296 subc_list_double_push (&percentile_list, 25);
297 subc_list_double_push (&percentile_list, 50);
298 subc_list_double_push (&percentile_list, 75);
301 grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
303 while (casegrouper_get_next_group (grouper, &group))
305 struct casereader *reader =
306 casereader_create_arithmetic_sequence (group, 1, 1);
308 run_examine (&cmd, reader, ds);
311 ok = casegrouper_destroy (grouper);
312 ok = proc_commit (ds) && ok;
314 if ( dependent_vars )
315 free (dependent_vars);
317 subc_list_double_destroy (&percentile_list);
319 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
326 show_npplot (const struct variable **dependent_var,
328 const struct xfactor *fctr)
332 for (v = 0; v < n_dep_var; ++v)
335 for (ll = ll_head (&fctr->result_list);
336 ll != ll_null (&fctr->result_list);
340 const struct factor_result *result =
341 ll_data (ll, struct factor_result, ll);
342 struct chart *npp, *dnpp;
343 struct casereader *reader;
346 ds_init_empty (&label);
347 ds_put_format (&label, "%s ", var_get_name (dependent_var[v]));
348 factor_to_string (fctr, result, &label);
350 np = (struct np *) result->metrics[v].np;
351 reader = casewriter_make_reader (np->writer);
352 npp = np_plot_create (np, reader, ds_cstr (&label));
353 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
357 if (npp == NULL || dnpp == NULL)
359 msg (MW, _("Not creating NP plot because data set is empty."));
369 statistic_destroy (&np->parent.parent);
376 show_histogram (const struct variable **dependent_var,
378 const struct xfactor *fctr)
382 for (v = 0; v < n_dep_var; ++v)
385 for (ll = ll_head (&fctr->result_list);
386 ll != ll_null (&fctr->result_list);
390 const struct factor_result *result =
391 ll_data (ll, struct factor_result, ll);
392 struct histogram *histogram;
395 histogram = (struct histogram *) result->metrics[v].histogram;
396 if (histogram == NULL)
398 /* Probably all values are SYSMIS. */
402 ds_init_empty (&str);
403 ds_put_format (&str, "%s ", var_get_name (dependent_var[v]));
405 factor_to_string (fctr, result, &str);
407 moments1_calculate ((struct moments1 *) result->metrics[v].moments,
408 &n, &mean, &var, NULL, NULL);
409 chart_submit (histogram_chart_create (histogram, ds_cstr (&str),
410 n, mean, sqrt (var), false));
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,
470 (struct box_whisker *) metrics->box_whisker,
472 metrics->box_whisker = NULL;
476 chart_submit (boxplot_get_chart (boxplot));
483 show_boxplot_variables (const struct variable **dependent_var,
485 const struct xfactor *fctr
489 const struct factor_result *result;
492 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
495 double y_min = DBL_MAX;
496 double y_max = -DBL_MAX;
497 struct boxplot *boxplot;
499 for (v = 0; v < n_dep_var; ++v)
501 const struct factor_metrics *metrics = &result->metrics[v];
502 const struct ll *max_ll = ll_head (extrema_list (metrics->maxima));
503 const struct ll *min_ll = ll_head (extrema_list (metrics->minima));
504 const struct extremum *max = ll_data (max_ll, struct extremum, ll);
505 const struct extremum *min = ll_data (min_ll, struct extremum, ll);
507 y_max = MAX (y_max, max->value);
508 y_min = MIN (y_min, min->value);
511 ds_init_empty (&title);
512 factor_to_string (fctr, result, &title);
513 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
516 for (v = 0; v < n_dep_var; ++v)
518 struct factor_metrics *metrics = &result->metrics[v];
519 boxplot_add_box (boxplot,
520 (struct box_whisker *) metrics->box_whisker,
521 var_get_name (dependent_var[v]));
522 metrics->box_whisker = NULL;
525 chart_submit (boxplot_get_chart (boxplot));
530 /* Show all the appropriate tables */
532 output_examine (const struct dictionary *dict)
536 show_summary (dependent_vars, n_dependent_vars, dict, &level0_factor);
538 if ( cmd.a_statistics[XMN_ST_EXTREME] )
539 show_extremes (dependent_vars, n_dependent_vars, &level0_factor);
541 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
542 show_descriptives (dependent_vars, n_dependent_vars, &level0_factor);
544 if ( cmd.sbc_percentiles)
545 show_percentiles (dependent_vars, n_dependent_vars, &level0_factor);
549 if (cmd.a_plot[XMN_PLT_BOXPLOT])
550 show_boxplot_groups (dependent_vars, n_dependent_vars, &level0_factor);
552 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
553 show_histogram (dependent_vars, n_dependent_vars, &level0_factor);
555 if (cmd.a_plot[XMN_PLT_NPPLOT])
556 show_npplot (dependent_vars, n_dependent_vars, &level0_factor);
559 for (ll = ll_head (&factor_list);
560 ll != ll_null (&factor_list); ll = ll_next (ll))
562 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
563 show_summary (dependent_vars, n_dependent_vars, dict, factor);
565 if ( cmd.a_statistics[XMN_ST_EXTREME] )
566 show_extremes (dependent_vars, n_dependent_vars, factor);
568 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
569 show_descriptives (dependent_vars, n_dependent_vars, factor);
571 if ( cmd.sbc_percentiles)
572 show_percentiles (dependent_vars, n_dependent_vars, factor);
574 if (cmd.a_plot[XMN_PLT_BOXPLOT])
576 if (cmd.cmp == XMN_GROUPS)
577 show_boxplot_groups (dependent_vars, n_dependent_vars, factor);
578 else if (cmd.cmp == XMN_VARIABLES)
579 show_boxplot_variables (dependent_vars, n_dependent_vars, factor);
582 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
583 show_histogram (dependent_vars, n_dependent_vars, factor);
585 if (cmd.a_plot[XMN_PLT_NPPLOT])
586 show_npplot (dependent_vars, n_dependent_vars, factor);
590 /* Parse the PERCENTILES subcommand */
592 xmn_custom_percentiles (struct lexer *lexer, struct dataset *ds UNUSED,
593 struct cmd_examine *p UNUSED, void *aux UNUSED)
595 lex_match (lexer, '=');
597 lex_match (lexer, '(');
599 while ( lex_is_number (lexer) )
601 subc_list_double_push (&percentile_list, lex_number (lexer));
605 lex_match (lexer, ',') ;
607 lex_match (lexer, ')');
609 lex_match (lexer, '=');
611 if ( lex_match_id (lexer, "HAVERAGE"))
612 percentile_algorithm = PC_HAVERAGE;
614 else if ( lex_match_id (lexer, "WAVERAGE"))
615 percentile_algorithm = PC_WAVERAGE;
617 else if ( lex_match_id (lexer, "ROUND"))
618 percentile_algorithm = PC_ROUND;
620 else if ( lex_match_id (lexer, "EMPIRICAL"))
621 percentile_algorithm = PC_EMPIRICAL;
623 else if ( lex_match_id (lexer, "AEMPIRICAL"))
624 percentile_algorithm = PC_AEMPIRICAL;
626 else if ( lex_match_id (lexer, "NONE"))
627 percentile_algorithm = PC_NONE;
630 if ( 0 == subc_list_double_count (&percentile_list))
632 subc_list_double_push (&percentile_list, 5);
633 subc_list_double_push (&percentile_list, 10);
634 subc_list_double_push (&percentile_list, 25);
635 subc_list_double_push (&percentile_list, 50);
636 subc_list_double_push (&percentile_list, 75);
637 subc_list_double_push (&percentile_list, 90);
638 subc_list_double_push (&percentile_list, 95);
644 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
646 xmn_custom_total (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
647 struct cmd_examine *p, void *aux UNUSED)
649 if ( p->sbc_nototal )
651 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
659 xmn_custom_nototal (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
660 struct cmd_examine *p, void *aux UNUSED)
664 msg (SE, _("%s and %s are mutually exclusive"), "TOTAL", "NOTOTAL");
673 /* Parser for the variables sub command
674 Returns 1 on success */
676 xmn_custom_variables (struct lexer *lexer, struct dataset *ds,
677 struct cmd_examine *cmd,
680 const struct dictionary *dict = dataset_dict (ds);
681 lex_match (lexer, '=');
683 if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
684 && lex_token (lexer) != T_ALL)
689 if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars,
690 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
692 free (dependent_vars);
696 assert (n_dependent_vars);
699 if ( lex_match (lexer, T_BY))
702 success = examine_parse_independent_vars (lexer, dict, cmd);
705 free (dependent_vars);
715 /* Parse the clause specifying the factors */
717 examine_parse_independent_vars (struct lexer *lexer,
718 const struct dictionary *dict,
719 struct cmd_examine *cmd)
722 struct xfactor *sf = xmalloc (sizeof *sf);
724 ll_init (&sf->result_list);
726 if ( (lex_token (lexer) != T_ID ||
727 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
728 && lex_token (lexer) != T_ALL)
734 sf->indep_var[0] = parse_variable (lexer, dict);
735 sf->indep_var[1] = NULL;
737 if ( lex_token (lexer) == T_BY )
739 lex_match (lexer, T_BY);
741 if ( (lex_token (lexer) != T_ID ||
742 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
743 && lex_token (lexer) != T_ALL)
749 sf->indep_var[1] = parse_variable (lexer, dict);
751 ll_push_tail (&factor_list, &sf->ll);
754 ll_push_tail (&factor_list, &sf->ll);
756 lex_match (lexer, ',');
758 if ( lex_token (lexer) == '.' || lex_token (lexer) == '/' )
761 success = examine_parse_independent_vars (lexer, dict, cmd);
770 examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
771 const struct dictionary *dict, struct xfactor *factor)
774 const struct variable *wv = dict_get_weight (dict);
777 struct factor_result *result = xzalloc (sizeof (*result));
780 for (i = 0; i < 2; i++)
781 if (factor->indep_var[i])
782 value_init (&result->value[i], var_get_width (factor->indep_var[i]));
784 result->metrics = xcalloc (n_dependent_vars, sizeof (*result->metrics));
786 if ( cmd->a_statistics[XMN_ST_EXTREME] )
787 n_extrema = cmd->st_n;
790 c = casereader_peek (reader, 0);
794 for (i = 0; i < 2; i++)
795 if (factor->indep_var[i])
796 value_copy (&result->value[i], case_data (c, factor->indep_var[i]),
797 var_get_width (factor->indep_var[i]));
801 for (v = 0; v < n_dependent_vars; ++v)
803 struct casewriter *writer;
804 struct casereader *input = casereader_clone (reader);
806 result->metrics[v].moments = moments1_create (MOMENT_KURTOSIS);
807 result->metrics[v].minima = extrema_create (n_extrema, EXTREME_MINIMA);
808 result->metrics[v].maxima = extrema_create (n_extrema, EXTREME_MAXIMA);
809 result->metrics[v].cmin = DBL_MAX;
811 if (cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
812 cmd->a_plot[XMN_PLT_BOXPLOT] ||
813 cmd->a_plot[XMN_PLT_NPPLOT] ||
814 cmd->sbc_percentiles)
816 /* In this case, we need to sort the data, so we create a sorting
818 struct subcase up_ordering;
819 subcase_init_var (&up_ordering, dependent_vars[v], SC_ASCEND);
820 writer = sort_create_writer (&up_ordering,
821 casereader_get_proto (reader));
822 subcase_destroy (&up_ordering);
826 /* but in this case, sorting is unnecessary, so an ordinary
827 casewriter is sufficient */
829 autopaging_writer_create (casereader_get_proto (reader));
833 /* Sort or just iterate, whilst calculating moments etc */
834 while ((c = casereader_read (input)) != NULL)
836 int n_vals = caseproto_get_n_widths (casereader_get_proto (reader));
837 const casenumber loc = case_data_idx (c, n_vals - 1)->f;
839 const double weight = wv ? case_data (c, wv)->f : 1.0;
840 const union value *value = case_data (c, dependent_vars[v]);
842 if (weight != SYSMIS)
843 minimize (&result->metrics[v].cmin, weight);
845 moments1_add (result->metrics[v].moments,
849 result->metrics[v].n += weight;
851 if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
852 result->metrics[v].n_valid += weight;
854 extrema_add (result->metrics[v].maxima,
859 extrema_add (result->metrics[v].minima,
864 casewriter_write (writer, c);
866 casereader_destroy (input);
867 result->metrics[v].up_reader = casewriter_make_reader (writer);
870 /* If percentiles or descriptives have been requested, then a
871 second pass through the data (which has now been sorted)
873 if ( cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
874 cmd->a_plot[XMN_PLT_BOXPLOT] ||
875 cmd->a_plot[XMN_PLT_NPPLOT] ||
876 cmd->sbc_percentiles)
878 for (v = 0; v < n_dependent_vars; ++v)
882 struct order_stats **os ;
883 struct factor_metrics *metric = &result->metrics[v];
885 metric->n_ptiles = percentile_list.n_data;
887 metric->ptl = xcalloc (metric->n_ptiles,
888 sizeof (struct percentile *));
890 metric->quartiles = xcalloc (3, sizeof (*metric->quartiles));
892 for (i = 0 ; i < metric->n_ptiles; ++i)
894 metric->ptl[i] = (struct percentile *)
895 percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
897 if ( percentile_list.data[i] == 25)
898 metric->quartiles[0] = metric->ptl[i];
899 else if ( percentile_list.data[i] == 50)
900 metric->quartiles[1] = metric->ptl[i];
901 else if ( percentile_list.data[i] == 75)
902 metric->quartiles[2] = metric->ptl[i];
905 metric->tukey_hinges = tukey_hinges_create (metric->n_valid, metric->cmin);
906 metric->trimmed_mean = trimmed_mean_create (metric->n_valid, 0.05);
908 n_os = metric->n_ptiles + 2;
910 if ( cmd->a_plot[XMN_PLT_NPPLOT] )
912 metric->np = np_create (metric->moments);
916 os = xcalloc (sizeof (struct order_stats *), n_os);
918 for (i = 0 ; i < metric->n_ptiles ; ++i )
920 os[i] = (struct order_stats *) metric->ptl[i];
923 os[i] = (struct order_stats *) metric->tukey_hinges;
924 os[i+1] = (struct order_stats *) metric->trimmed_mean;
926 if (cmd->a_plot[XMN_PLT_NPPLOT])
927 os[i+2] = metric->np;
929 order_stats_accumulate (os, n_os,
930 casereader_clone (metric->up_reader),
931 wv, dependent_vars[v], MV_ANY);
936 /* FIXME: Do this in the above loop */
937 if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
940 struct casereader *input = casereader_clone (reader);
942 for (v = 0; v < n_dependent_vars; ++v)
944 const struct extremum *max, *min;
945 struct factor_metrics *metric = &result->metrics[v];
947 const struct ll_list *max_list =
948 extrema_list (result->metrics[v].maxima);
950 const struct ll_list *min_list =
951 extrema_list (result->metrics[v].minima);
953 if ( ll_is_empty (max_list))
955 msg (MW, _("Not creating plot because data set is empty."));
959 assert (! ll_is_empty (min_list));
961 max = (const struct extremum *)
962 ll_data (ll_head(max_list), struct extremum, ll);
964 min = (const struct extremum *)
965 ll_data (ll_head (min_list), struct extremum, ll);
967 metric->histogram = histogram_create (10, min->value, max->value);
970 while ((c = casereader_read (input)) != NULL)
972 const double weight = wv ? case_data (c, wv)->f : 1.0;
974 for (v = 0; v < n_dependent_vars; ++v)
976 struct factor_metrics *metric = &result->metrics[v];
977 if ( metric->histogram)
978 histogram_add ((struct histogram *) metric->histogram,
979 case_data (c, dependent_vars[v])->f, weight);
983 casereader_destroy (input);
986 /* In this case, a third iteration is required */
987 if (cmd->a_plot[XMN_PLT_BOXPLOT])
989 for (v = 0; v < n_dependent_vars; ++v)
991 struct factor_metrics *metric = &result->metrics[v];
992 int n_vals = caseproto_get_n_widths (casereader_get_proto (
995 metric->box_whisker =
996 box_whisker_create ((struct tukey_hinges *) metric->tukey_hinges,
997 cmd->v_id, n_vals - 1);
999 order_stats_accumulate ((struct order_stats **) &metric->box_whisker,
1001 casereader_clone (metric->up_reader),
1002 wv, dependent_vars[v], MV_ANY);
1006 ll_push_tail (&factor->result_list, &result->ll);
1007 casereader_destroy (reader);
1012 run_examine (struct cmd_examine *cmd, struct casereader *input,
1016 const struct dictionary *dict = dataset_dict (ds);
1018 struct casereader *level0 = casereader_clone (input);
1020 c = casereader_peek (input, 0);
1023 casereader_destroy (input);
1027 output_split_file_values (ds, c);
1030 ll_init (&level0_factor.result_list);
1032 examine_group (cmd, level0, 0, dict, &level0_factor);
1034 for (ll = ll_head (&factor_list);
1035 ll != ll_null (&factor_list);
1038 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
1040 struct casereader *group = NULL;
1041 struct casereader *level1;
1042 struct casegrouper *grouper1 = NULL;
1044 level1 = casereader_clone (input);
1045 level1 = sort_execute_1var (level1, factor->indep_var[0]);
1046 grouper1 = casegrouper_create_vars (level1, &factor->indep_var[0], 1);
1048 while (casegrouper_get_next_group (grouper1, &group))
1050 struct casereader *group_copy = casereader_clone (group);
1052 if ( !factor->indep_var[1])
1053 examine_group (cmd, group_copy, 1, dict, factor);
1057 struct casereader *group2 = NULL;
1058 struct casegrouper *grouper2 = NULL;
1060 group_copy = sort_execute_1var (group_copy,
1061 factor->indep_var[1]);
1063 grouper2 = casegrouper_create_vars (group_copy,
1064 &factor->indep_var[1], 1);
1066 while (casegrouper_get_next_group (grouper2, &group2))
1068 examine_group (cmd, group2, 2, dict, factor);
1071 casegrouper_destroy (grouper2);
1074 casereader_destroy (group);
1076 casegrouper_destroy (grouper1);
1079 casereader_destroy (input);
1081 output_examine (dict);
1083 factor_destroy (&level0_factor);
1087 for (ll = ll_head (&factor_list);
1088 ll != ll_null (&factor_list);
1091 struct xfactor *f = ll_data (ll, struct xfactor, ll);
1100 show_summary (const struct variable **dependent_var, int n_dep_var,
1101 const struct dictionary *dict,
1102 const struct xfactor *fctr)
1104 const struct variable *wv = dict_get_weight (dict);
1105 const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
1107 static const char *subtitle[]=
1115 int heading_columns = 1;
1117 const int heading_rows = 3;
1118 struct tab_table *tbl;
1125 if ( fctr->indep_var[0] )
1127 heading_columns = 2;
1129 if ( fctr->indep_var[1] )
1131 heading_columns = 3;
1135 n_rows *= ll_count (&fctr->result_list);
1136 n_rows += heading_rows;
1138 n_cols = heading_columns + 6;
1140 tbl = tab_create (n_cols, n_rows, 0);
1141 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1143 tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
1145 /* Outline the box */
1150 n_cols - 1, n_rows - 1);
1152 /* Vertical lines for the data only */
1157 n_cols - 1, n_rows - 1);
1160 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1161 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
1162 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, heading_rows -1 );
1164 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1167 tab_title (tbl, _("Case Processing Summary"));
1169 tab_joint_text (tbl, heading_columns, 0,
1171 TAB_CENTER | TAT_TITLE,
1174 /* Remove lines ... */
1181 for (j = 0 ; j < 3 ; ++j)
1183 tab_text (tbl, heading_columns + j * 2 , 2, TAB_CENTER | TAT_TITLE,
1186 tab_text (tbl, heading_columns + j * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1189 tab_joint_text (tbl, heading_columns + j * 2 , 1,
1190 heading_columns + j * 2 + 1, 1,
1191 TAB_CENTER | TAT_TITLE,
1194 tab_box (tbl, -1, -1,
1196 heading_columns + j * 2, 1,
1197 heading_columns + j * 2 + 1, 1);
1201 /* Titles for the independent variables */
1202 if ( fctr->indep_var[0] )
1204 tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1205 var_to_string (fctr->indep_var[0]));
1207 if ( fctr->indep_var[1] )
1209 tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1210 var_to_string (fctr->indep_var[1]));
1214 for (v = 0 ; v < n_dep_var ; ++v)
1218 const union value *last_value = NULL;
1221 tab_hline (tbl, TAL_1, 0, n_cols -1 ,
1222 v * ll_count (&fctr->result_list)
1227 v * ll_count (&fctr->result_list) + heading_rows,
1228 TAB_LEFT | TAT_TITLE,
1229 var_to_string (dependent_var[v])
1233 for (ll = ll_head (&fctr->result_list);
1234 ll != ll_null (&fctr->result_list); ll = ll_next (ll))
1237 const struct factor_result *result =
1238 ll_data (ll, struct factor_result, ll);
1240 if ( fctr->indep_var[0] )
1243 if ( last_value == NULL ||
1244 !value_equal (last_value, &result->value[0],
1245 var_get_width (fctr->indep_var[0])))
1249 last_value = &result->value[0];
1250 ds_init_empty (&str);
1252 var_append_value_name (fctr->indep_var[0], &result->value[0],
1257 v * ll_count (&fctr->result_list),
1258 TAB_LEFT | TAT_TITLE,
1263 if ( fctr->indep_var[1] && j > 0)
1264 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1266 v * ll_count (&fctr->result_list));
1269 if ( fctr->indep_var[1])
1273 ds_init_empty (&str);
1275 var_append_value_name (fctr->indep_var[1],
1276 &result->value[1], &str);
1280 v * ll_count (&fctr->result_list),
1281 TAB_LEFT | TAT_TITLE,
1289 moments1_calculate (result->metrics[v].moments,
1290 &n, &result->metrics[v].mean,
1291 &result->metrics[v].variance,
1292 &result->metrics[v].skewness,
1293 &result->metrics[v].kurtosis);
1295 result->metrics[v].se_mean = sqrt (result->metrics[v].variance / n) ;
1298 tab_double (tbl, heading_columns,
1299 heading_rows + j + v * ll_count (&fctr->result_list),
1303 tab_text (tbl, heading_columns + 1,
1304 heading_rows + j + v * ll_count (&fctr->result_list),
1305 TAB_RIGHT | TAT_PRINTF,
1306 "%g%%", n * 100.0 / result->metrics[v].n);
1309 tab_double (tbl, heading_columns + 2,
1310 heading_rows + j + v * ll_count (&fctr->result_list),
1312 result->metrics[v].n - n,
1315 tab_text (tbl, heading_columns + 3,
1316 heading_rows + j + v * ll_count (&fctr->result_list),
1317 TAB_RIGHT | TAT_PRINTF,
1319 (result->metrics[v].n - n) * 100.0 / result->metrics[v].n
1322 /* Total Valid + Missing */
1323 tab_double (tbl, heading_columns + 4,
1324 heading_rows + j + v * ll_count (&fctr->result_list),
1326 result->metrics[v].n,
1329 tab_text (tbl, heading_columns + 5,
1330 heading_rows + j + v * ll_count (&fctr->result_list),
1331 TAB_RIGHT | TAT_PRINTF,
1333 (result->metrics[v].n) * 100.0 / result->metrics[v].n
1344 #define DESCRIPTIVE_ROWS 13
1347 show_descriptives (const struct variable **dependent_var,
1349 const struct xfactor *fctr)
1352 int heading_columns = 3;
1354 const int heading_rows = 1;
1355 struct tab_table *tbl;
1362 if ( fctr->indep_var[0] )
1364 heading_columns = 4;
1366 if ( fctr->indep_var[1] )
1368 heading_columns = 5;
1372 n_rows *= ll_count (&fctr->result_list) * DESCRIPTIVE_ROWS;
1373 n_rows += heading_rows;
1375 n_cols = heading_columns + 2;
1377 tbl = tab_create (n_cols, n_rows, 0);
1378 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1380 tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
1382 /* Outline the box */
1387 n_cols - 1, n_rows - 1);
1390 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1391 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1393 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1396 if ( fctr->indep_var[0])
1397 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1399 if ( fctr->indep_var[1])
1400 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1402 for (v = 0 ; v < n_dep_var ; ++v )
1407 const int row_var_start =
1408 v * DESCRIPTIVE_ROWS * ll_count(&fctr->result_list);
1412 heading_rows + row_var_start,
1413 TAB_LEFT | TAT_TITLE,
1414 var_to_string (dependent_var[v])
1417 for (ll = ll_head (&fctr->result_list);
1418 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1420 const struct factor_result *result =
1421 ll_data (ll, struct factor_result, ll);
1424 gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0) / 2.0,
1425 result->metrics[v].n - 1);
1427 if ( i > 0 || v > 0 )
1429 const int left_col = (i == 0) ? 0 : 1;
1430 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1431 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS);
1434 if ( fctr->indep_var[0])
1437 ds_init_empty (&vstr);
1438 var_append_value_name (fctr->indep_var[0],
1439 &result->value[0], &vstr);
1442 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1451 tab_text (tbl, n_cols - 4,
1452 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1456 tab_text (tbl, n_cols - 4,
1457 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1458 TAB_LEFT | TAT_PRINTF,
1459 _("%g%% Confidence Interval for Mean"),
1460 cmd.n_cinterval[0]);
1462 tab_text (tbl, n_cols - 3,
1463 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1467 tab_text (tbl, n_cols - 3,
1468 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1472 tab_text (tbl, n_cols - 4,
1473 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1474 TAB_LEFT | TAT_PRINTF,
1475 _("5%% Trimmed Mean"));
1477 tab_text (tbl, n_cols - 4,
1478 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1482 tab_text (tbl, n_cols - 4,
1483 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1487 tab_text (tbl, n_cols - 4,
1488 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1490 _("Std. Deviation"));
1492 tab_text (tbl, n_cols - 4,
1493 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1497 tab_text (tbl, n_cols - 4,
1498 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1502 tab_text (tbl, n_cols - 4,
1503 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1507 tab_text (tbl, n_cols - 4,
1508 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1510 _("Interquartile Range"));
1513 tab_text (tbl, n_cols - 4,
1514 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1518 tab_text (tbl, n_cols - 4,
1519 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1524 /* Now the statistics ... */
1526 tab_double (tbl, n_cols - 2,
1527 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1529 result->metrics[v].mean,
1532 tab_double (tbl, n_cols - 1,
1533 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1535 result->metrics[v].se_mean,
1539 tab_double (tbl, n_cols - 2,
1540 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1542 result->metrics[v].mean - t *
1543 result->metrics[v].se_mean,
1546 tab_double (tbl, n_cols - 2,
1547 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1549 result->metrics[v].mean + t *
1550 result->metrics[v].se_mean,
1554 tab_double (tbl, n_cols - 2,
1555 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1557 trimmed_mean_calculate ((struct trimmed_mean *) result->metrics[v].trimmed_mean),
1561 tab_double (tbl, n_cols - 2,
1562 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1564 percentile_calculate (result->metrics[v].quartiles[1], percentile_algorithm),
1568 tab_double (tbl, n_cols - 2,
1569 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1571 result->metrics[v].variance,
1574 tab_double (tbl, n_cols - 2,
1575 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1577 sqrt (result->metrics[v].variance),
1580 tab_double (tbl, n_cols - 2,
1581 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1583 percentile_calculate (result->metrics[v].quartiles[2],
1584 percentile_algorithm) -
1585 percentile_calculate (result->metrics[v].quartiles[0],
1586 percentile_algorithm),
1590 tab_double (tbl, n_cols - 2,
1591 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1593 result->metrics[v].skewness,
1596 tab_double (tbl, n_cols - 2,
1597 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1599 result->metrics[v].kurtosis,
1602 tab_double (tbl, n_cols - 1,
1603 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1605 calc_seskew (result->metrics[v].n),
1608 tab_double (tbl, n_cols - 1,
1609 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1611 calc_sekurt (result->metrics[v].n),
1615 struct extremum *minimum, *maximum ;
1617 struct ll *max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1618 struct ll *min_ll = ll_head (extrema_list (result->metrics[v].minima));
1620 maximum = ll_data (max_ll, struct extremum, ll);
1621 minimum = ll_data (min_ll, struct extremum, ll);
1623 tab_double (tbl, n_cols - 2,
1624 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1629 tab_double (tbl, n_cols - 2,
1630 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1635 tab_double (tbl, n_cols - 2,
1636 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1638 maximum->value - minimum->value,
1644 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1646 tab_title (tbl, _("Descriptives"));
1648 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1651 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1660 show_extremes (const struct variable **dependent_var,
1662 const struct xfactor *fctr)
1665 int heading_columns = 3;
1667 const int heading_rows = 1;
1668 struct tab_table *tbl;
1675 if ( fctr->indep_var[0] )
1677 heading_columns = 4;
1679 if ( fctr->indep_var[1] )
1681 heading_columns = 5;
1685 n_rows *= ll_count (&fctr->result_list) * cmd.st_n * 2;
1686 n_rows += heading_rows;
1688 n_cols = heading_columns + 2;
1690 tbl = tab_create (n_cols, n_rows, 0);
1691 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1693 tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
1695 /* Outline the box */
1700 n_cols - 1, n_rows - 1);
1703 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1704 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1705 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1707 if ( fctr->indep_var[0])
1708 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1710 if ( fctr->indep_var[1])
1711 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1713 for (v = 0 ; v < n_dep_var ; ++v )
1717 const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
1721 heading_rows + row_var_start,
1722 TAB_LEFT | TAT_TITLE,
1723 var_to_string (dependent_var[v])
1726 for (ll = ll_head (&fctr->result_list);
1727 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1732 const int row_result_start = i * cmd.st_n * 2;
1734 const struct factor_result *result =
1735 ll_data (ll, struct factor_result, ll);
1738 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1739 heading_rows + row_var_start + row_result_start);
1741 tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
1742 heading_rows + row_var_start + row_result_start + cmd.st_n);
1744 for ( e = 1; e <= cmd.st_n; ++e )
1746 tab_text (tbl, n_cols - 3,
1747 heading_rows + row_var_start + row_result_start + e - 1,
1748 TAB_RIGHT | TAT_PRINTF,
1751 tab_text (tbl, n_cols - 3,
1752 heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
1753 TAB_RIGHT | TAT_PRINTF,
1758 min_ll = ll_head (extrema_list (result->metrics[v].minima));
1759 for (e = 0; e < cmd.st_n;)
1761 struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
1762 double weight = minimum->weight;
1764 while (weight-- > 0 && e < cmd.st_n)
1766 tab_double (tbl, n_cols - 1,
1767 heading_rows + row_var_start + row_result_start + cmd.st_n + e,
1773 tab_fixed (tbl, n_cols - 2,
1774 heading_rows + row_var_start +
1775 row_result_start + cmd.st_n + e,
1782 min_ll = ll_next (min_ll);
1786 max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1787 for (e = 0; e < cmd.st_n;)
1789 struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
1790 double weight = maximum->weight;
1792 while (weight-- > 0 && e < cmd.st_n)
1794 tab_double (tbl, n_cols - 1,
1795 heading_rows + row_var_start +
1796 row_result_start + e,
1802 tab_fixed (tbl, n_cols - 2,
1803 heading_rows + row_var_start +
1804 row_result_start + e,
1811 max_ll = ll_next (max_ll);
1815 if ( fctr->indep_var[0])
1818 ds_init_empty (&vstr);
1819 var_append_value_name (fctr->indep_var[0],
1820 &result->value[0], &vstr);
1823 heading_rows + row_var_start + row_result_start,
1832 tab_text (tbl, n_cols - 4,
1833 heading_rows + row_var_start + row_result_start,
1837 tab_text (tbl, n_cols - 4,
1838 heading_rows + row_var_start + row_result_start + cmd.st_n,
1844 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1847 tab_title (tbl, _("Extreme Values"));
1850 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1854 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1860 #define PERCENTILE_ROWS 2
1863 show_percentiles (const struct variable **dependent_var,
1865 const struct xfactor *fctr)
1869 int heading_columns = 2;
1871 const int n_percentiles = subc_list_double_count (&percentile_list);
1872 const int heading_rows = 2;
1873 struct tab_table *tbl;
1880 if ( fctr->indep_var[0] )
1882 heading_columns = 3;
1884 if ( fctr->indep_var[1] )
1886 heading_columns = 4;
1890 n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
1891 n_rows += heading_rows;
1893 n_cols = heading_columns + n_percentiles;
1895 tbl = tab_create (n_cols, n_rows, 0);
1896 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1898 tab_dim (tbl, tab_natural_dimensions, NULL, NULL);
1900 /* Outline the box */
1905 n_cols - 1, n_rows - 1);
1908 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1909 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1911 if ( fctr->indep_var[0])
1912 tab_text (tbl, 1, 1, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1914 if ( fctr->indep_var[1])
1915 tab_text (tbl, 2, 1, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1917 for (v = 0 ; v < n_dep_var ; ++v )
1923 const int row_var_start =
1924 v * PERCENTILE_ROWS * ll_count(&fctr->result_list);
1928 heading_rows + row_var_start,
1929 TAB_LEFT | TAT_TITLE,
1930 var_to_string (dependent_var[v])
1933 for (ll = ll_head (&fctr->result_list);
1934 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1937 const struct factor_result *result =
1938 ll_data (ll, struct factor_result, ll);
1940 if ( i > 0 || v > 0 )
1942 const int left_col = (i == 0) ? 0 : 1;
1943 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1944 heading_rows + row_var_start + i * PERCENTILE_ROWS);
1947 if ( fctr->indep_var[0])
1950 ds_init_empty (&vstr);
1951 var_append_value_name (fctr->indep_var[0],
1952 &result->value[0], &vstr);
1955 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1964 tab_text (tbl, n_cols - n_percentiles - 1,
1965 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1967 ptile_alg_desc [percentile_algorithm]);
1970 tab_text (tbl, n_cols - n_percentiles - 1,
1971 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1973 _("Tukey's Hinges"));
1976 tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1);
1978 tukey_hinges_calculate ((struct tukey_hinges *) result->metrics[v].tukey_hinges,
1981 for (j = 0; j < n_percentiles; ++j)
1983 double hinge = SYSMIS;
1984 tab_double (tbl, n_cols - n_percentiles + j,
1985 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1987 percentile_calculate (result->metrics[v].ptl[j],
1988 percentile_algorithm),
1992 if ( result->metrics[v].ptl[j]->ptile == 0.5)
1994 else if ( result->metrics[v].ptl[j]->ptile == 0.25)
1996 else if ( result->metrics[v].ptl[j]->ptile == 0.75)
1999 if ( hinge != SYSMIS)
2000 tab_double (tbl, n_cols - n_percentiles + j,
2001 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
2011 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
2013 tab_title (tbl, _("Percentiles"));
2016 for (i = 0 ; i < n_percentiles; ++i )
2018 tab_text (tbl, n_cols - n_percentiles + i, 1,
2019 TAB_CENTER | TAT_TITLE | TAT_PRINTF,
2021 subc_list_double_at (&percentile_list, i)
2027 tab_joint_text (tbl,
2028 n_cols - n_percentiles, 0,
2030 TAB_CENTER | TAT_TITLE,
2033 /* Vertical lines for the data only */
2037 n_cols - n_percentiles, 1,
2038 n_cols - 1, n_rows - 1);
2040 tab_hline (tbl, TAL_1, n_cols - n_percentiles, n_cols - 1, 1);
2048 factor_to_string_concise (const struct xfactor *fctr,
2049 const struct factor_result *result,
2053 if (fctr->indep_var[0])
2055 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2057 if ( fctr->indep_var[1] )
2059 ds_put_cstr (str, ",");
2061 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2063 ds_put_cstr (str, ")");
2070 factor_to_string (const struct xfactor *fctr,
2071 const struct factor_result *result,
2075 if (fctr->indep_var[0])
2077 ds_put_format (str, "(%s = ", var_get_name (fctr->indep_var[0]));
2079 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2081 if ( fctr->indep_var[1] )
2083 ds_put_cstr (str, ",");
2084 ds_put_format (str, "%s = ", var_get_name (fctr->indep_var[1]));
2086 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2088 ds_put_cstr (str, ")");