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/message.h>
47 #include <libpspp/misc.h>
48 #include <libpspp/str.h>
49 #include <math/moments.h>
50 #include <output/chart-item.h>
51 #include <output/charts/boxplot.h>
52 #include <output/charts/np-plot.h>
53 #include <output/tab.h>
59 #define _(msgid) gettext (msgid)
60 #define N_(msgid) msgid
63 #include <output/charts/plot-hist.h>
64 #include <math/histogram.h>
71 missing=miss:pairwise/!listwise,
73 incl:include/!exclude;
74 +compare=cmp:variables/!groups;
77 +plot[plt_]=stemleaf,boxplot,npplot,:spreadlevel(*d:n),histogram,all,none;
79 +statistics[st_]=descriptives,:extreme(*d:n),all,none.
87 static struct cmd_examine cmd;
89 static const struct variable **dependent_vars;
90 static size_t n_dependent_vars;
94 static subc_list_double percentile_list;
95 static enum pc_alg percentile_algorithm;
99 struct moments1 *moments;
101 struct percentile **ptl;
104 struct tukey_hinges *tukey_hinges;
105 struct box_whisker *box_whisker;
106 struct trimmed_mean *trimmed_mean;
107 struct histogram *histogram;
110 /* Three quartiles indexing into PTL */
111 struct percentile **quartiles;
113 /* A reader sorted in ASCENDING order */
114 struct casereader *up_reader;
116 /* The minimum value of all the weights */
119 /* Sum of all weights, including those for missing values */
122 /* Sum of weights of non_missing values */
135 struct extrema *minima;
136 struct extrema *maxima;
143 union value value[2];
145 /* An array of factor metrics, one for each variable */
146 struct factor_metrics *metrics;
151 /* We need to make a list of this structure */
154 /* The independent variable */
155 const struct variable const* indep_var[2];
157 /* A list of results for this factor */
158 struct ll_list result_list ;
163 factor_destroy (struct xfactor *fctr)
165 struct ll *ll = ll_head (&fctr->result_list);
166 while (ll != ll_null (&fctr->result_list))
169 struct factor_result *result =
170 ll_data (ll, struct factor_result, ll);
173 for (v = 0; v < n_dependent_vars; ++v)
176 moments1_destroy (result->metrics[v].moments);
177 extrema_destroy (result->metrics[v].minima);
178 extrema_destroy (result->metrics[v].maxima);
179 statistic_destroy (&result->metrics[v].trimmed_mean->parent.parent);
180 statistic_destroy (&result->metrics[v].tukey_hinges->parent.parent);
181 statistic_destroy (&result->metrics[v].box_whisker->parent.parent);
182 statistic_destroy (&result->metrics[v].histogram->parent);
183 for (i = 0 ; i < result->metrics[v].n_ptiles; ++i)
184 statistic_destroy (&result->metrics[v].ptl[i]->parent.parent);
185 free (result->metrics[v].ptl);
186 free (result->metrics[v].quartiles);
187 casereader_destroy (result->metrics[v].up_reader);
190 for (i = 0; i < 2; i++)
191 if (fctr->indep_var[i])
192 value_destroy (&result->value[i],
193 var_get_width (fctr->indep_var[i]));
194 free (result->metrics);
200 static struct xfactor level0_factor;
201 static struct ll_list factor_list;
203 /* Parse the clause specifying the factors */
204 static int examine_parse_independent_vars (struct lexer *lexer,
205 const struct dictionary *dict,
206 struct cmd_examine *cmd);
208 /* Output functions */
209 static void show_summary (const struct variable **dependent_var, int n_dep_var,
210 const struct dictionary *dict,
211 const struct xfactor *f);
214 static void show_descriptives (const struct variable **dependent_var,
216 const struct xfactor *f);
219 static void show_percentiles (const struct variable **dependent_var,
221 const struct xfactor *f);
224 static void show_extremes (const struct variable **dependent_var,
226 const struct xfactor *f);
231 /* Per Split function */
232 static void run_examine (struct cmd_examine *, struct casereader *,
235 static void output_examine (const struct dictionary *dict);
238 void factor_calc (const struct ccase *c, int case_no,
239 double weight, bool case_missing);
242 /* Represent a factor as a string, so it can be
243 printed in a human readable fashion */
244 static void factor_to_string (const struct xfactor *fctr,
245 const struct factor_result *result,
248 /* Represent a factor as a string, so it can be
249 printed in a human readable fashion,
250 but sacrificing some readablility for the sake of brevity */
252 factor_to_string_concise (const struct xfactor *fctr,
253 const struct factor_result *result,
259 /* Categories of missing values to exclude. */
260 static enum mv_class exclude_values;
263 cmd_examine (struct lexer *lexer, struct dataset *ds)
265 struct casegrouper *grouper;
266 struct casereader *group;
269 subc_list_double_create (&percentile_list);
270 percentile_algorithm = PC_HAVERAGE;
272 ll_init (&factor_list);
274 if ( !parse_examine (lexer, ds, &cmd, NULL) )
276 subc_list_double_destroy (&percentile_list);
280 /* If /MISSING=INCLUDE is set, then user missing values are ignored */
281 exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
283 if ( cmd.st_n == SYSMIS )
286 if ( ! cmd.sbc_cinterval)
287 cmd.n_cinterval[0] = 95.0;
289 /* If descriptives have been requested, make sure the
290 quartiles are calculated */
291 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
293 subc_list_double_push (&percentile_list, 25);
294 subc_list_double_push (&percentile_list, 50);
295 subc_list_double_push (&percentile_list, 75);
298 grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
300 while (casegrouper_get_next_group (grouper, &group))
302 struct casereader *reader =
303 casereader_create_arithmetic_sequence (group, 1, 1);
305 run_examine (&cmd, reader, ds);
308 ok = casegrouper_destroy (grouper);
309 ok = proc_commit (ds) && ok;
311 if ( dependent_vars )
312 free (dependent_vars);
314 subc_list_double_destroy (&percentile_list);
316 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
323 show_npplot (const struct variable **dependent_var,
325 const struct xfactor *fctr)
329 for (v = 0; v < n_dep_var; ++v)
332 for (ll = ll_head (&fctr->result_list);
333 ll != ll_null (&fctr->result_list);
337 const struct factor_result *result =
338 ll_data (ll, struct factor_result, ll);
339 struct chart_item *npp, *dnpp;
340 struct casereader *reader;
343 ds_init_empty (&label);
344 ds_put_format (&label, "%s ", var_get_name (dependent_var[v]));
345 factor_to_string (fctr, result, &label);
347 np = result->metrics[v].np;
348 reader = casewriter_make_reader (np->writer);
349 npp = np_plot_create (np, reader, ds_cstr (&label));
350 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
354 if (npp == NULL || dnpp == NULL)
356 msg (MW, _("Not creating NP plot because data set is empty."));
357 chart_item_unref (npp);
358 chart_item_unref (dnpp);
362 chart_item_submit (npp);
363 chart_item_submit (dnpp);
366 statistic_destroy (&np->parent.parent);
367 casereader_destroy (reader);
374 show_histogram (const struct variable **dependent_var,
376 const struct xfactor *fctr)
380 for (v = 0; v < n_dep_var; ++v)
383 for (ll = ll_head (&fctr->result_list);
384 ll != ll_null (&fctr->result_list);
388 const struct factor_result *result =
389 ll_data (ll, struct factor_result, ll);
390 struct histogram *histogram;
393 histogram = result->metrics[v].histogram;
394 if (histogram == NULL)
396 /* Probably all values are SYSMIS. */
400 ds_init_empty (&str);
401 ds_put_format (&str, "%s ", var_get_name (dependent_var[v]));
403 factor_to_string (fctr, result, &str);
405 moments1_calculate (result->metrics[v].moments,
406 &n, &mean, &var, NULL, NULL);
407 chart_item_submit (histogram_chart_create (histogram->gsl_hist,
408 ds_cstr (&str), n, mean,
419 show_boxplot_groups (const struct variable **dependent_var,
421 const struct xfactor *fctr)
425 for (v = 0; v < n_dep_var; ++v)
427 const struct factor_result *result;
428 struct boxplot *boxplot;
429 double y_min = DBL_MAX;
430 double y_max = -DBL_MAX;
433 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
435 struct factor_metrics *metrics = &result->metrics[v];
436 const struct ll_list *max_list = extrema_list (metrics->maxima);
437 const struct ll_list *min_list = extrema_list (metrics->minima);
438 const struct extremum *max, *min;
440 if ( ll_is_empty (max_list))
442 msg (MW, _("Not creating plot because data set is empty."));
446 max = ll_data (ll_head(max_list), struct extremum, ll);
447 min = ll_data (ll_head (min_list), struct extremum, ll);
449 y_max = MAX (y_max, max->value);
450 y_min = MIN (y_min, min->value);
453 if (fctr->indep_var[0])
454 title = xasprintf (_("Boxplot of %s vs. %s"),
455 var_to_string (dependent_var[v]),
456 var_to_string (fctr->indep_var[0]));
458 title = xasprintf (_("Boxplot of %s"),
459 var_to_string (dependent_var[v]));
460 boxplot = boxplot_create (y_min, y_max, title);
463 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
465 struct factor_metrics *metrics = &result->metrics[v];
466 struct string str = DS_EMPTY_INITIALIZER;
467 factor_to_string_concise (fctr, result, &str);
468 boxplot_add_box (boxplot, metrics->box_whisker, ds_cstr (&str));
469 metrics->box_whisker = NULL;
473 boxplot_submit (boxplot);
480 show_boxplot_variables (const struct variable **dependent_var,
482 const struct xfactor *fctr
486 const struct factor_result *result;
489 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
492 double y_min = DBL_MAX;
493 double y_max = -DBL_MAX;
494 struct boxplot *boxplot;
496 for (v = 0; v < n_dep_var; ++v)
498 const struct factor_metrics *metrics = &result->metrics[v];
499 const struct ll *max_ll = ll_head (extrema_list (metrics->maxima));
500 const struct ll *min_ll = ll_head (extrema_list (metrics->minima));
501 const struct extremum *max = ll_data (max_ll, struct extremum, ll);
502 const struct extremum *min = ll_data (min_ll, struct extremum, ll);
504 y_max = MAX (y_max, max->value);
505 y_min = MIN (y_min, min->value);
508 ds_init_empty (&title);
509 factor_to_string (fctr, result, &title);
510 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
513 for (v = 0; v < n_dep_var; ++v)
515 struct factor_metrics *metrics = &result->metrics[v];
516 boxplot_add_box (boxplot, metrics->box_whisker,
517 var_get_name (dependent_var[v]));
518 metrics->box_whisker = NULL;
521 boxplot_submit (boxplot);
526 /* Show all the appropriate tables */
528 output_examine (const struct dictionary *dict)
532 show_summary (dependent_vars, n_dependent_vars, dict, &level0_factor);
534 if ( cmd.a_statistics[XMN_ST_EXTREME] )
535 show_extremes (dependent_vars, n_dependent_vars, &level0_factor);
537 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
538 show_descriptives (dependent_vars, n_dependent_vars, &level0_factor);
540 if ( cmd.sbc_percentiles)
541 show_percentiles (dependent_vars, n_dependent_vars, &level0_factor);
545 if (cmd.a_plot[XMN_PLT_BOXPLOT])
546 show_boxplot_groups (dependent_vars, n_dependent_vars, &level0_factor);
548 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
549 show_histogram (dependent_vars, n_dependent_vars, &level0_factor);
551 if (cmd.a_plot[XMN_PLT_NPPLOT])
552 show_npplot (dependent_vars, n_dependent_vars, &level0_factor);
555 for (ll = ll_head (&factor_list);
556 ll != ll_null (&factor_list); ll = ll_next (ll))
558 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
559 show_summary (dependent_vars, n_dependent_vars, dict, factor);
561 if ( cmd.a_statistics[XMN_ST_EXTREME] )
562 show_extremes (dependent_vars, n_dependent_vars, factor);
564 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
565 show_descriptives (dependent_vars, n_dependent_vars, factor);
567 if ( cmd.sbc_percentiles)
568 show_percentiles (dependent_vars, n_dependent_vars, factor);
570 if (cmd.a_plot[XMN_PLT_BOXPLOT])
572 if (cmd.cmp == XMN_GROUPS)
573 show_boxplot_groups (dependent_vars, n_dependent_vars, factor);
574 else if (cmd.cmp == XMN_VARIABLES)
575 show_boxplot_variables (dependent_vars, n_dependent_vars, factor);
578 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
579 show_histogram (dependent_vars, n_dependent_vars, factor);
581 if (cmd.a_plot[XMN_PLT_NPPLOT])
582 show_npplot (dependent_vars, n_dependent_vars, factor);
586 /* Parse the PERCENTILES subcommand */
588 xmn_custom_percentiles (struct lexer *lexer, struct dataset *ds UNUSED,
589 struct cmd_examine *p UNUSED, void *aux UNUSED)
591 lex_match (lexer, '=');
593 lex_match (lexer, '(');
595 while ( lex_is_number (lexer) )
597 subc_list_double_push (&percentile_list, lex_number (lexer));
601 lex_match (lexer, ',') ;
603 lex_match (lexer, ')');
605 lex_match (lexer, '=');
607 if ( lex_match_id (lexer, "HAVERAGE"))
608 percentile_algorithm = PC_HAVERAGE;
610 else if ( lex_match_id (lexer, "WAVERAGE"))
611 percentile_algorithm = PC_WAVERAGE;
613 else if ( lex_match_id (lexer, "ROUND"))
614 percentile_algorithm = PC_ROUND;
616 else if ( lex_match_id (lexer, "EMPIRICAL"))
617 percentile_algorithm = PC_EMPIRICAL;
619 else if ( lex_match_id (lexer, "AEMPIRICAL"))
620 percentile_algorithm = PC_AEMPIRICAL;
622 else if ( lex_match_id (lexer, "NONE"))
623 percentile_algorithm = PC_NONE;
626 if ( 0 == subc_list_double_count (&percentile_list))
628 subc_list_double_push (&percentile_list, 5);
629 subc_list_double_push (&percentile_list, 10);
630 subc_list_double_push (&percentile_list, 25);
631 subc_list_double_push (&percentile_list, 50);
632 subc_list_double_push (&percentile_list, 75);
633 subc_list_double_push (&percentile_list, 90);
634 subc_list_double_push (&percentile_list, 95);
640 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
642 xmn_custom_total (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
643 struct cmd_examine *p, void *aux UNUSED)
645 if ( p->sbc_nototal )
647 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
655 xmn_custom_nototal (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
656 struct cmd_examine *p, void *aux UNUSED)
660 msg (SE, _("%s and %s are mutually exclusive"), "TOTAL", "NOTOTAL");
669 /* Parser for the variables sub command
670 Returns 1 on success */
672 xmn_custom_variables (struct lexer *lexer, struct dataset *ds,
673 struct cmd_examine *cmd,
676 const struct dictionary *dict = dataset_dict (ds);
677 lex_match (lexer, '=');
679 if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
680 && lex_token (lexer) != T_ALL)
685 if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars,
686 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
688 free (dependent_vars);
692 assert (n_dependent_vars);
695 if ( lex_match (lexer, T_BY))
698 success = examine_parse_independent_vars (lexer, dict, cmd);
701 free (dependent_vars);
711 /* Parse the clause specifying the factors */
713 examine_parse_independent_vars (struct lexer *lexer,
714 const struct dictionary *dict,
715 struct cmd_examine *cmd)
718 struct xfactor *sf = xmalloc (sizeof *sf);
720 ll_init (&sf->result_list);
722 if ( (lex_token (lexer) != T_ID ||
723 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
724 && lex_token (lexer) != T_ALL)
730 sf->indep_var[0] = parse_variable (lexer, dict);
731 sf->indep_var[1] = NULL;
733 if ( lex_token (lexer) == T_BY )
735 lex_match (lexer, T_BY);
737 if ( (lex_token (lexer) != T_ID ||
738 dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
739 && lex_token (lexer) != T_ALL)
745 sf->indep_var[1] = parse_variable (lexer, dict);
747 ll_push_tail (&factor_list, &sf->ll);
750 ll_push_tail (&factor_list, &sf->ll);
752 lex_match (lexer, ',');
754 if ( lex_token (lexer) == '.' || lex_token (lexer) == '/' )
757 success = examine_parse_independent_vars (lexer, dict, cmd);
766 examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
767 const struct dictionary *dict, struct xfactor *factor)
770 const struct variable *wv = dict_get_weight (dict);
773 struct factor_result *result = xzalloc (sizeof (*result));
776 for (i = 0; i < 2; i++)
777 if (factor->indep_var[i])
778 value_init (&result->value[i], var_get_width (factor->indep_var[i]));
780 result->metrics = xcalloc (n_dependent_vars, sizeof (*result->metrics));
782 if ( cmd->a_statistics[XMN_ST_EXTREME] )
783 n_extrema = cmd->st_n;
786 c = casereader_peek (reader, 0);
790 for (i = 0; i < 2; i++)
791 if (factor->indep_var[i])
792 value_copy (&result->value[i], case_data (c, factor->indep_var[i]),
793 var_get_width (factor->indep_var[i]));
797 for (v = 0; v < n_dependent_vars; ++v)
799 struct casewriter *writer;
800 struct casereader *input = casereader_clone (reader);
802 result->metrics[v].moments = moments1_create (MOMENT_KURTOSIS);
803 result->metrics[v].minima = extrema_create (n_extrema, EXTREME_MINIMA);
804 result->metrics[v].maxima = extrema_create (n_extrema, EXTREME_MAXIMA);
805 result->metrics[v].cmin = DBL_MAX;
807 if (cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
808 cmd->a_plot[XMN_PLT_BOXPLOT] ||
809 cmd->a_plot[XMN_PLT_NPPLOT] ||
810 cmd->sbc_percentiles)
812 /* In this case, we need to sort the data, so we create a sorting
814 struct subcase up_ordering;
815 subcase_init_var (&up_ordering, dependent_vars[v], SC_ASCEND);
816 writer = sort_create_writer (&up_ordering,
817 casereader_get_proto (reader));
818 subcase_destroy (&up_ordering);
822 /* but in this case, sorting is unnecessary, so an ordinary
823 casewriter is sufficient */
825 autopaging_writer_create (casereader_get_proto (reader));
829 /* Sort or just iterate, whilst calculating moments etc */
830 while ((c = casereader_read (input)) != NULL)
832 int n_vals = caseproto_get_n_widths (casereader_get_proto (reader));
833 const casenumber loc = case_data_idx (c, n_vals - 1)->f;
835 const double weight = wv ? case_data (c, wv)->f : 1.0;
836 const union value *value = case_data (c, dependent_vars[v]);
838 if (weight != SYSMIS)
839 minimize (&result->metrics[v].cmin, weight);
841 moments1_add (result->metrics[v].moments,
845 result->metrics[v].n += weight;
847 if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
848 result->metrics[v].n_valid += weight;
850 extrema_add (result->metrics[v].maxima,
855 extrema_add (result->metrics[v].minima,
860 casewriter_write (writer, c);
862 casereader_destroy (input);
863 result->metrics[v].up_reader = casewriter_make_reader (writer);
866 /* If percentiles or descriptives have been requested, then a
867 second pass through the data (which has now been sorted)
869 if ( cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
870 cmd->a_plot[XMN_PLT_BOXPLOT] ||
871 cmd->a_plot[XMN_PLT_NPPLOT] ||
872 cmd->sbc_percentiles)
874 for (v = 0; v < n_dependent_vars; ++v)
878 struct order_stats **os ;
879 struct factor_metrics *metric = &result->metrics[v];
881 metric->n_ptiles = percentile_list.n_data;
883 metric->ptl = xcalloc (metric->n_ptiles, sizeof *metric->ptl);
885 metric->quartiles = xcalloc (3, sizeof (*metric->quartiles));
887 for (i = 0 ; i < metric->n_ptiles; ++i)
889 metric->ptl[i] = percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
891 if ( percentile_list.data[i] == 25)
892 metric->quartiles[0] = metric->ptl[i];
893 else if ( percentile_list.data[i] == 50)
894 metric->quartiles[1] = metric->ptl[i];
895 else if ( percentile_list.data[i] == 75)
896 metric->quartiles[2] = metric->ptl[i];
899 metric->tukey_hinges = tukey_hinges_create (metric->n_valid, metric->cmin);
900 metric->trimmed_mean = trimmed_mean_create (metric->n_valid, 0.05);
902 n_os = metric->n_ptiles + 2;
904 if ( cmd->a_plot[XMN_PLT_NPPLOT] )
906 metric->np = np_create (metric->moments);
910 os = xcalloc (n_os, sizeof *os);
912 for (i = 0 ; i < metric->n_ptiles ; ++i )
914 os[i] = &metric->ptl[i]->parent;
917 os[i] = &metric->tukey_hinges->parent;
918 os[i+1] = &metric->trimmed_mean->parent;
920 if (cmd->a_plot[XMN_PLT_NPPLOT])
921 os[i+2] = &metric->np->parent;
923 order_stats_accumulate (os, n_os,
924 casereader_clone (metric->up_reader),
925 wv, dependent_vars[v], MV_ANY);
930 /* FIXME: Do this in the above loop */
931 if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
934 struct casereader *input = casereader_clone (reader);
936 for (v = 0; v < n_dependent_vars; ++v)
938 const struct extremum *max, *min;
939 struct factor_metrics *metric = &result->metrics[v];
941 const struct ll_list *max_list =
942 extrema_list (result->metrics[v].maxima);
944 const struct ll_list *min_list =
945 extrema_list (result->metrics[v].minima);
947 if ( ll_is_empty (max_list))
949 msg (MW, _("Not creating plot because data set is empty."));
953 assert (! ll_is_empty (min_list));
955 max = (const struct extremum *)
956 ll_data (ll_head(max_list), struct extremum, ll);
958 min = (const struct extremum *)
959 ll_data (ll_head (min_list), struct extremum, ll);
961 metric->histogram = histogram_create (10, min->value, max->value);
964 while ((c = casereader_read (input)) != NULL)
966 const double weight = wv ? case_data (c, wv)->f : 1.0;
968 for (v = 0; v < n_dependent_vars; ++v)
970 struct factor_metrics *metric = &result->metrics[v];
971 if ( metric->histogram)
972 histogram_add (metric->histogram,
973 case_data (c, dependent_vars[v])->f, weight);
977 casereader_destroy (input);
980 /* In this case, a third iteration is required */
981 if (cmd->a_plot[XMN_PLT_BOXPLOT])
983 for (v = 0; v < n_dependent_vars; ++v)
985 struct factor_metrics *metric = &result->metrics[v];
986 int n_vals = caseproto_get_n_widths (casereader_get_proto (
988 struct order_stats *os;
990 metric->box_whisker =
991 box_whisker_create ( metric->tukey_hinges, cmd->v_id, n_vals - 1);
993 os = &metric->box_whisker->parent;
994 order_stats_accumulate ( &os, 1,
995 casereader_clone (metric->up_reader),
996 wv, dependent_vars[v], MV_ANY);
1000 ll_push_tail (&factor->result_list, &result->ll);
1001 casereader_destroy (reader);
1006 run_examine (struct cmd_examine *cmd, struct casereader *input,
1010 const struct dictionary *dict = dataset_dict (ds);
1012 struct casereader *level0 = casereader_clone (input);
1014 c = casereader_peek (input, 0);
1017 casereader_destroy (input);
1021 output_split_file_values (ds, c);
1024 ll_init (&level0_factor.result_list);
1026 examine_group (cmd, level0, 0, dict, &level0_factor);
1028 for (ll = ll_head (&factor_list);
1029 ll != ll_null (&factor_list);
1032 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
1034 struct casereader *group = NULL;
1035 struct casereader *level1;
1036 struct casegrouper *grouper1 = NULL;
1038 level1 = casereader_clone (input);
1039 level1 = sort_execute_1var (level1, factor->indep_var[0]);
1040 grouper1 = casegrouper_create_vars (level1, &factor->indep_var[0], 1);
1042 while (casegrouper_get_next_group (grouper1, &group))
1044 struct casereader *group_copy = casereader_clone (group);
1046 if ( !factor->indep_var[1])
1047 examine_group (cmd, group_copy, 1, dict, factor);
1051 struct casereader *group2 = NULL;
1052 struct casegrouper *grouper2 = NULL;
1054 group_copy = sort_execute_1var (group_copy,
1055 factor->indep_var[1]);
1057 grouper2 = casegrouper_create_vars (group_copy,
1058 &factor->indep_var[1], 1);
1060 while (casegrouper_get_next_group (grouper2, &group2))
1062 examine_group (cmd, group2, 2, dict, factor);
1065 casegrouper_destroy (grouper2);
1068 casereader_destroy (group);
1070 casegrouper_destroy (grouper1);
1073 casereader_destroy (input);
1075 output_examine (dict);
1077 factor_destroy (&level0_factor);
1081 for (ll = ll_head (&factor_list);
1082 ll != ll_null (&factor_list);
1085 struct xfactor *f = ll_data (ll, struct xfactor, ll);
1094 show_summary (const struct variable **dependent_var, int n_dep_var,
1095 const struct dictionary *dict,
1096 const struct xfactor *fctr)
1098 const struct variable *wv = dict_get_weight (dict);
1099 const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
1101 static const char *subtitle[]=
1109 int heading_columns = 1;
1111 const int heading_rows = 3;
1112 struct tab_table *tbl;
1119 if ( fctr->indep_var[0] )
1121 heading_columns = 2;
1123 if ( fctr->indep_var[1] )
1125 heading_columns = 3;
1129 n_rows *= ll_count (&fctr->result_list);
1130 n_rows += heading_rows;
1132 n_cols = heading_columns + 6;
1134 tbl = tab_create (n_cols, n_rows);
1135 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1137 /* Outline the box */
1142 n_cols - 1, n_rows - 1);
1144 /* Vertical lines for the data only */
1149 n_cols - 1, n_rows - 1);
1152 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1153 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
1154 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, heading_rows -1 );
1156 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1159 tab_title (tbl, _("Case Processing Summary"));
1161 tab_joint_text (tbl, heading_columns, 0,
1163 TAB_CENTER | TAT_TITLE,
1166 /* Remove lines ... */
1173 for (j = 0 ; j < 3 ; ++j)
1175 tab_text (tbl, heading_columns + j * 2 , 2, TAB_CENTER | TAT_TITLE,
1178 tab_text (tbl, heading_columns + j * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1181 tab_joint_text (tbl, heading_columns + j * 2 , 1,
1182 heading_columns + j * 2 + 1, 1,
1183 TAB_CENTER | TAT_TITLE,
1186 tab_box (tbl, -1, -1,
1188 heading_columns + j * 2, 1,
1189 heading_columns + j * 2 + 1, 1);
1193 /* Titles for the independent variables */
1194 if ( fctr->indep_var[0] )
1196 tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1197 var_to_string (fctr->indep_var[0]));
1199 if ( fctr->indep_var[1] )
1201 tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1202 var_to_string (fctr->indep_var[1]));
1206 for (v = 0 ; v < n_dep_var ; ++v)
1210 const union value *last_value = NULL;
1213 tab_hline (tbl, TAL_1, 0, n_cols -1 ,
1214 v * ll_count (&fctr->result_list)
1219 v * ll_count (&fctr->result_list) + heading_rows,
1220 TAB_LEFT | TAT_TITLE,
1221 var_to_string (dependent_var[v])
1225 for (ll = ll_head (&fctr->result_list);
1226 ll != ll_null (&fctr->result_list); ll = ll_next (ll))
1229 const struct factor_result *result =
1230 ll_data (ll, struct factor_result, ll);
1232 if ( fctr->indep_var[0] )
1235 if ( last_value == NULL ||
1236 !value_equal (last_value, &result->value[0],
1237 var_get_width (fctr->indep_var[0])))
1241 last_value = &result->value[0];
1242 ds_init_empty (&str);
1244 var_append_value_name (fctr->indep_var[0], &result->value[0],
1249 v * ll_count (&fctr->result_list),
1250 TAB_LEFT | TAT_TITLE,
1255 if ( fctr->indep_var[1] && j > 0)
1256 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1258 v * ll_count (&fctr->result_list));
1261 if ( fctr->indep_var[1])
1265 ds_init_empty (&str);
1267 var_append_value_name (fctr->indep_var[1],
1268 &result->value[1], &str);
1272 v * ll_count (&fctr->result_list),
1273 TAB_LEFT | TAT_TITLE,
1281 moments1_calculate (result->metrics[v].moments,
1282 &n, &result->metrics[v].mean,
1283 &result->metrics[v].variance,
1284 &result->metrics[v].skewness,
1285 &result->metrics[v].kurtosis);
1287 result->metrics[v].se_mean = sqrt (result->metrics[v].variance / n) ;
1290 tab_double (tbl, heading_columns,
1291 heading_rows + j + v * ll_count (&fctr->result_list),
1295 tab_text_format (tbl, heading_columns + 1,
1296 heading_rows + j + v * ll_count (&fctr->result_list),
1298 "%g%%", n * 100.0 / result->metrics[v].n);
1301 tab_double (tbl, heading_columns + 2,
1302 heading_rows + j + v * ll_count (&fctr->result_list),
1304 result->metrics[v].n - n,
1307 tab_text_format (tbl, heading_columns + 3,
1308 heading_rows + j + v * ll_count (&fctr->result_list),
1311 (result->metrics[v].n - n) * 100.0 / result->metrics[v].n
1314 /* Total Valid + Missing */
1315 tab_double (tbl, heading_columns + 4,
1316 heading_rows + j + v * ll_count (&fctr->result_list),
1318 result->metrics[v].n,
1321 tab_text_format (tbl, heading_columns + 5,
1322 heading_rows + j + v * ll_count (&fctr->result_list),
1325 ((result->metrics[v].n) * 100.0
1326 / result->metrics[v].n));
1336 #define DESCRIPTIVE_ROWS 13
1339 show_descriptives (const struct variable **dependent_var,
1341 const struct xfactor *fctr)
1344 int heading_columns = 3;
1346 const int heading_rows = 1;
1347 struct tab_table *tbl;
1354 if ( fctr->indep_var[0] )
1356 heading_columns = 4;
1358 if ( fctr->indep_var[1] )
1360 heading_columns = 5;
1364 n_rows *= ll_count (&fctr->result_list) * DESCRIPTIVE_ROWS;
1365 n_rows += heading_rows;
1367 n_cols = heading_columns + 2;
1369 tbl = tab_create (n_cols, n_rows);
1370 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1372 /* Outline the box */
1377 n_cols - 1, n_rows - 1);
1380 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1381 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1383 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1386 if ( fctr->indep_var[0])
1387 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1389 if ( fctr->indep_var[1])
1390 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1392 for (v = 0 ; v < n_dep_var ; ++v )
1397 const int row_var_start =
1398 v * DESCRIPTIVE_ROWS * ll_count(&fctr->result_list);
1402 heading_rows + row_var_start,
1403 TAB_LEFT | TAT_TITLE,
1404 var_to_string (dependent_var[v])
1407 for (ll = ll_head (&fctr->result_list);
1408 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1410 const struct factor_result *result =
1411 ll_data (ll, struct factor_result, ll);
1414 gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0) / 2.0,
1415 result->metrics[v].n - 1);
1417 if ( i > 0 || v > 0 )
1419 const int left_col = (i == 0) ? 0 : 1;
1420 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1421 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS);
1424 if ( fctr->indep_var[0])
1427 ds_init_empty (&vstr);
1428 var_append_value_name (fctr->indep_var[0],
1429 &result->value[0], &vstr);
1432 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1441 tab_text (tbl, n_cols - 4,
1442 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1446 tab_text_format (tbl, n_cols - 4,
1447 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1449 _("%g%% Confidence Interval for Mean"),
1450 cmd.n_cinterval[0]);
1452 tab_text (tbl, n_cols - 3,
1453 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1457 tab_text (tbl, n_cols - 3,
1458 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1462 tab_text (tbl, n_cols - 4,
1463 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1464 TAB_LEFT, _("5% Trimmed Mean"));
1466 tab_text (tbl, n_cols - 4,
1467 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1471 tab_text (tbl, n_cols - 4,
1472 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1476 tab_text (tbl, n_cols - 4,
1477 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1479 _("Std. Deviation"));
1481 tab_text (tbl, n_cols - 4,
1482 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1486 tab_text (tbl, n_cols - 4,
1487 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1491 tab_text (tbl, n_cols - 4,
1492 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1496 tab_text (tbl, n_cols - 4,
1497 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1499 _("Interquartile Range"));
1502 tab_text (tbl, n_cols - 4,
1503 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1507 tab_text (tbl, n_cols - 4,
1508 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1513 /* Now the statistics ... */
1515 tab_double (tbl, n_cols - 2,
1516 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1518 result->metrics[v].mean,
1521 tab_double (tbl, n_cols - 1,
1522 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1524 result->metrics[v].se_mean,
1528 tab_double (tbl, n_cols - 2,
1529 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1531 result->metrics[v].mean - t *
1532 result->metrics[v].se_mean,
1535 tab_double (tbl, n_cols - 2,
1536 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1538 result->metrics[v].mean + t *
1539 result->metrics[v].se_mean,
1543 tab_double (tbl, n_cols - 2,
1544 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1546 trimmed_mean_calculate (result->metrics[v].trimmed_mean),
1550 tab_double (tbl, n_cols - 2,
1551 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1553 percentile_calculate (result->metrics[v].quartiles[1], percentile_algorithm),
1557 tab_double (tbl, n_cols - 2,
1558 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1560 result->metrics[v].variance,
1563 tab_double (tbl, n_cols - 2,
1564 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1566 sqrt (result->metrics[v].variance),
1569 tab_double (tbl, n_cols - 2,
1570 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1572 percentile_calculate (result->metrics[v].quartiles[2],
1573 percentile_algorithm) -
1574 percentile_calculate (result->metrics[v].quartiles[0],
1575 percentile_algorithm),
1579 tab_double (tbl, n_cols - 2,
1580 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1582 result->metrics[v].skewness,
1585 tab_double (tbl, n_cols - 2,
1586 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1588 result->metrics[v].kurtosis,
1591 tab_double (tbl, n_cols - 1,
1592 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1594 calc_seskew (result->metrics[v].n),
1597 tab_double (tbl, n_cols - 1,
1598 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1600 calc_sekurt (result->metrics[v].n),
1604 struct extremum *minimum, *maximum ;
1606 struct ll *max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1607 struct ll *min_ll = ll_head (extrema_list (result->metrics[v].minima));
1609 maximum = ll_data (max_ll, struct extremum, ll);
1610 minimum = ll_data (min_ll, struct extremum, ll);
1612 tab_double (tbl, n_cols - 2,
1613 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1618 tab_double (tbl, n_cols - 2,
1619 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1624 tab_double (tbl, n_cols - 2,
1625 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1627 maximum->value - minimum->value,
1633 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1635 tab_title (tbl, _("Descriptives"));
1637 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1640 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1649 show_extremes (const struct variable **dependent_var,
1651 const struct xfactor *fctr)
1654 int heading_columns = 3;
1656 const int heading_rows = 1;
1657 struct tab_table *tbl;
1664 if ( fctr->indep_var[0] )
1666 heading_columns = 4;
1668 if ( fctr->indep_var[1] )
1670 heading_columns = 5;
1674 n_rows *= ll_count (&fctr->result_list) * cmd.st_n * 2;
1675 n_rows += heading_rows;
1677 n_cols = heading_columns + 2;
1679 tbl = tab_create (n_cols, n_rows);
1680 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1682 /* Outline the box */
1687 n_cols - 1, n_rows - 1);
1690 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1691 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1692 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1694 if ( fctr->indep_var[0])
1695 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1697 if ( fctr->indep_var[1])
1698 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1700 for (v = 0 ; v < n_dep_var ; ++v )
1704 const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
1708 heading_rows + row_var_start,
1709 TAB_LEFT | TAT_TITLE,
1710 var_to_string (dependent_var[v])
1713 for (ll = ll_head (&fctr->result_list);
1714 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1719 const int row_result_start = i * cmd.st_n * 2;
1721 const struct factor_result *result =
1722 ll_data (ll, struct factor_result, ll);
1725 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1726 heading_rows + row_var_start + row_result_start);
1728 tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
1729 heading_rows + row_var_start + row_result_start + cmd.st_n);
1731 for ( e = 1; e <= cmd.st_n; ++e )
1733 tab_text_format (tbl, n_cols - 3,
1734 heading_rows + row_var_start + row_result_start + e - 1,
1738 tab_text_format (tbl, n_cols - 3,
1739 heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
1745 min_ll = ll_head (extrema_list (result->metrics[v].minima));
1746 for (e = 0; e < cmd.st_n;)
1748 struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
1749 double weight = minimum->weight;
1751 while (weight-- > 0 && e < cmd.st_n)
1753 tab_double (tbl, n_cols - 1,
1754 heading_rows + row_var_start + row_result_start + cmd.st_n + e,
1760 tab_fixed (tbl, n_cols - 2,
1761 heading_rows + row_var_start +
1762 row_result_start + cmd.st_n + e,
1769 min_ll = ll_next (min_ll);
1772 max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1773 for (e = 0; e < cmd.st_n;)
1775 struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
1776 double weight = maximum->weight;
1778 while (weight-- > 0 && e < cmd.st_n)
1780 tab_double (tbl, n_cols - 1,
1781 heading_rows + row_var_start +
1782 row_result_start + e,
1788 tab_fixed (tbl, n_cols - 2,
1789 heading_rows + row_var_start +
1790 row_result_start + e,
1797 max_ll = ll_next (max_ll);
1801 if ( fctr->indep_var[0])
1804 ds_init_empty (&vstr);
1805 var_append_value_name (fctr->indep_var[0],
1806 &result->value[0], &vstr);
1809 heading_rows + row_var_start + row_result_start,
1818 tab_text (tbl, n_cols - 4,
1819 heading_rows + row_var_start + row_result_start,
1823 tab_text (tbl, n_cols - 4,
1824 heading_rows + row_var_start + row_result_start + cmd.st_n,
1830 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1833 tab_title (tbl, _("Extreme Values"));
1836 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1840 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1846 #define PERCENTILE_ROWS 2
1849 show_percentiles (const struct variable **dependent_var,
1851 const struct xfactor *fctr)
1855 int heading_columns = 2;
1857 const int n_percentiles = subc_list_double_count (&percentile_list);
1858 const int heading_rows = 2;
1859 struct tab_table *tbl;
1866 if ( fctr->indep_var[0] )
1868 heading_columns = 3;
1870 if ( fctr->indep_var[1] )
1872 heading_columns = 4;
1876 n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
1877 n_rows += heading_rows;
1879 n_cols = heading_columns + n_percentiles;
1881 tbl = tab_create (n_cols, n_rows);
1882 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1884 /* Outline the box */
1889 n_cols - 1, n_rows - 1);
1892 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1893 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1895 if ( fctr->indep_var[0])
1896 tab_text (tbl, 1, 1, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1898 if ( fctr->indep_var[1])
1899 tab_text (tbl, 2, 1, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1901 for (v = 0 ; v < n_dep_var ; ++v )
1907 const int row_var_start =
1908 v * PERCENTILE_ROWS * ll_count(&fctr->result_list);
1912 heading_rows + row_var_start,
1913 TAB_LEFT | TAT_TITLE,
1914 var_to_string (dependent_var[v])
1917 for (ll = ll_head (&fctr->result_list);
1918 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1921 const struct factor_result *result =
1922 ll_data (ll, struct factor_result, ll);
1924 if ( i > 0 || v > 0 )
1926 const int left_col = (i == 0) ? 0 : 1;
1927 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1928 heading_rows + row_var_start + i * PERCENTILE_ROWS);
1931 if ( fctr->indep_var[0])
1934 ds_init_empty (&vstr);
1935 var_append_value_name (fctr->indep_var[0],
1936 &result->value[0], &vstr);
1939 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1948 tab_text (tbl, n_cols - n_percentiles - 1,
1949 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1951 ptile_alg_desc [percentile_algorithm]);
1954 tab_text (tbl, n_cols - n_percentiles - 1,
1955 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1957 _("Tukey's Hinges"));
1960 tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1);
1962 tukey_hinges_calculate (result->metrics[v].tukey_hinges, hinges);
1964 for (j = 0; j < n_percentiles; ++j)
1966 double hinge = SYSMIS;
1967 tab_double (tbl, n_cols - n_percentiles + j,
1968 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1970 percentile_calculate (result->metrics[v].ptl[j],
1971 percentile_algorithm),
1975 if ( result->metrics[v].ptl[j]->ptile == 0.5)
1977 else if ( result->metrics[v].ptl[j]->ptile == 0.25)
1979 else if ( result->metrics[v].ptl[j]->ptile == 0.75)
1982 if ( hinge != SYSMIS)
1983 tab_double (tbl, n_cols - n_percentiles + j,
1984 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1994 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1996 tab_title (tbl, _("Percentiles"));
1999 for (i = 0 ; i < n_percentiles; ++i )
2001 tab_text_format (tbl, n_cols - n_percentiles + i, 1,
2002 TAB_CENTER | TAT_TITLE,
2004 subc_list_double_at (&percentile_list, i));
2009 tab_joint_text (tbl,
2010 n_cols - n_percentiles, 0,
2012 TAB_CENTER | TAT_TITLE,
2015 /* Vertical lines for the data only */
2019 n_cols - n_percentiles, 1,
2020 n_cols - 1, n_rows - 1);
2022 tab_hline (tbl, TAL_1, n_cols - n_percentiles, n_cols - 1, 1);
2030 factor_to_string_concise (const struct xfactor *fctr,
2031 const struct factor_result *result,
2035 if (fctr->indep_var[0])
2037 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2039 if ( fctr->indep_var[1] )
2041 ds_put_cstr (str, ",");
2043 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2045 ds_put_cstr (str, ")");
2052 factor_to_string (const struct xfactor *fctr,
2053 const struct factor_result *result,
2057 if (fctr->indep_var[0])
2059 ds_put_format (str, "(%s = ", var_get_name (fctr->indep_var[0]));
2061 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2063 if ( fctr->indep_var[1] )
2065 ds_put_cstr (str, ",");
2066 ds_put_format (str, "%s = ", var_get_name (fctr->indep_var[1]));
2068 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2070 ds_put_cstr (str, ")");