1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2008, 2009, 2010, 2011 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>
24 #include "data/case.h"
25 #include "data/casegrouper.h"
26 #include "data/casereader.h"
27 #include "data/casewriter.h"
28 #include "data/dataset.h"
29 #include "data/dictionary.h"
30 #include "data/subcase.h"
31 #include "data/value-labels.h"
32 #include "data/variable.h"
33 #include "language/command.h"
34 #include "language/dictionary/split-file.h"
35 #include "language/lexer/lexer.h"
36 #include "libpspp/compiler.h"
37 #include "libpspp/message.h"
38 #include "libpspp/misc.h"
39 #include "libpspp/str.h"
40 #include "math/box-whisker.h"
41 #include "math/extrema.h"
42 #include "math/histogram.h"
43 #include "math/moments.h"
45 #include "math/order-stats.h"
46 #include "math/percentiles.h"
47 #include "math/sort.h"
48 #include "math/trimmed-mean.h"
49 #include "math/tukey-hinges.h"
50 #include "output/chart-item.h"
51 #include "output/charts/boxplot.h"
52 #include "output/charts/np-plot.h"
53 #include "output/charts/plot-hist.h"
54 #include "output/tab.h"
56 #include "gl/minmax.h"
57 #include "gl/xalloc.h"
60 #define _(msgid) gettext (msgid)
61 #define N_(msgid) msgid
70 missing=miss:pairwise/!listwise,
72 incl:include/!exclude;
73 +compare=cmp:variables/!groups;
76 +plot[plt_]=stemleaf,boxplot,npplot,:spreadlevel(*d:n),histogram,all,none;
78 +statistics[st_]=descriptives,:extreme(*d:n),all,none.
86 static struct cmd_examine cmd;
88 static const struct variable **dependent_vars;
89 static size_t n_dependent_vars;
93 static subc_list_double percentile_list;
94 static enum pc_alg percentile_algorithm;
98 struct moments1 *moments;
100 struct percentile **ptl;
103 struct tukey_hinges *tukey_hinges;
104 struct box_whisker *box_whisker;
105 struct trimmed_mean *trimmed_mean;
106 struct histogram *histogram;
109 /* Three quartiles indexing into PTL */
110 struct percentile **quartiles;
112 /* A reader sorted in ASCENDING order */
113 struct casereader *up_reader;
115 /* The minimum value of all the weights */
118 /* Sum of all weights, including those for missing values */
121 /* Sum of weights of non_missing values */
134 struct extrema *minima;
135 struct extrema *maxima;
142 union value value[2];
144 /* An array of factor metrics, one for each variable */
145 struct factor_metrics *metrics;
150 /* We need to make a list of this structure */
153 /* The independent variable */
154 const struct variable const* indep_var[2];
156 /* A list of results for this factor */
157 struct ll_list result_list ;
162 factor_destroy (struct xfactor *fctr)
164 struct ll *ll = ll_head (&fctr->result_list);
165 while (ll != ll_null (&fctr->result_list))
168 struct factor_result *result =
169 ll_data (ll, struct factor_result, ll);
172 for (v = 0; v < n_dependent_vars; ++v)
175 moments1_destroy (result->metrics[v].moments);
176 extrema_destroy (result->metrics[v].minima);
177 extrema_destroy (result->metrics[v].maxima);
178 statistic_destroy (&result->metrics[v].trimmed_mean->parent.parent);
179 statistic_destroy (&result->metrics[v].tukey_hinges->parent.parent);
180 statistic_destroy (&result->metrics[v].box_whisker->parent.parent);
181 statistic_destroy (&result->metrics[v].histogram->parent);
182 for (i = 0 ; i < result->metrics[v].n_ptiles; ++i)
183 statistic_destroy (&result->metrics[v].ptl[i]->parent.parent);
184 free (result->metrics[v].ptl);
185 free (result->metrics[v].quartiles);
186 casereader_destroy (result->metrics[v].up_reader);
189 for (i = 0; i < 2; i++)
190 if (fctr->indep_var[i])
191 value_destroy (&result->value[i],
192 var_get_width (fctr->indep_var[i]));
193 free (result->metrics);
199 static struct xfactor level0_factor;
200 static struct ll_list factor_list;
202 /* Parse the clause specifying the factors */
203 static int examine_parse_independent_vars (struct lexer *lexer,
204 const struct dictionary *dict,
205 struct cmd_examine *cmd);
207 /* Output functions */
208 static void show_summary (const struct variable **dependent_var, int n_dep_var,
209 const struct dictionary *dict,
210 const struct xfactor *f);
213 static void show_descriptives (const struct variable **dependent_var,
215 const struct xfactor *f);
218 static void show_percentiles (const struct variable **dependent_var,
220 const struct xfactor *f);
223 static void show_extremes (const struct variable **dependent_var,
225 const struct xfactor *f);
230 /* Per Split function */
231 static void run_examine (struct cmd_examine *, struct casereader *,
234 static void output_examine (const struct dictionary *dict);
237 void factor_calc (const struct ccase *c, int case_no,
238 double weight, bool case_missing);
241 /* Represent a factor as a string, so it can be
242 printed in a human readable fashion */
243 static void factor_to_string (const struct xfactor *fctr,
244 const struct factor_result *result,
247 /* Represent a factor as a string, so it can be
248 printed in a human readable fashion,
249 but sacrificing some readablility for the sake of brevity */
251 factor_to_string_concise (const struct xfactor *fctr,
252 const struct factor_result *result,
258 /* Categories of missing values to exclude. */
259 static enum mv_class exclude_values;
262 cmd_examine (struct lexer *lexer, struct dataset *ds)
264 struct casegrouper *grouper;
265 struct casereader *group;
268 subc_list_double_create (&percentile_list);
269 percentile_algorithm = PC_HAVERAGE;
271 ll_init (&factor_list);
273 if ( !parse_examine (lexer, ds, &cmd, NULL) )
275 subc_list_double_destroy (&percentile_list);
279 /* If /MISSING=INCLUDE is set, then user missing values are ignored */
280 exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
282 if ( cmd.st_n == SYSMIS )
285 if ( ! cmd.sbc_cinterval)
286 cmd.n_cinterval[0] = 95.0;
288 /* If descriptives have been requested, make sure the
289 quartiles are calculated */
290 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
292 subc_list_double_push (&percentile_list, 25);
293 subc_list_double_push (&percentile_list, 50);
294 subc_list_double_push (&percentile_list, 75);
297 grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
299 while (casegrouper_get_next_group (grouper, &group))
301 struct casereader *reader =
302 casereader_create_arithmetic_sequence (group, 1, 1);
304 run_examine (&cmd, reader, ds);
307 ok = casegrouper_destroy (grouper);
308 ok = proc_commit (ds) && ok;
310 if ( dependent_vars )
311 free (dependent_vars);
313 subc_list_double_destroy (&percentile_list);
315 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
322 show_npplot (const struct variable **dependent_var,
324 const struct xfactor *fctr)
328 for (v = 0; v < n_dep_var; ++v)
331 for (ll = ll_head (&fctr->result_list);
332 ll != ll_null (&fctr->result_list);
336 const struct factor_result *result =
337 ll_data (ll, struct factor_result, ll);
338 struct chart_item *npp, *dnpp;
339 struct casereader *reader;
342 ds_init_empty (&label);
343 ds_put_format (&label, "%s ", var_get_name (dependent_var[v]));
344 factor_to_string (fctr, result, &label);
346 np = result->metrics[v].np;
347 reader = casewriter_make_reader (np->writer);
348 npp = np_plot_create (np, reader, ds_cstr (&label));
349 dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
353 if (npp == NULL || dnpp == NULL)
355 msg (MW, _("Not creating NP plot because data set is empty."));
356 chart_item_unref (npp);
357 chart_item_unref (dnpp);
361 chart_item_submit (npp);
362 chart_item_submit (dnpp);
365 statistic_destroy (&np->parent.parent);
366 casereader_destroy (reader);
373 show_histogram (const struct variable **dependent_var,
375 const struct xfactor *fctr)
379 for (v = 0; v < n_dep_var; ++v)
382 for (ll = ll_head (&fctr->result_list);
383 ll != ll_null (&fctr->result_list);
387 const struct factor_result *result =
388 ll_data (ll, struct factor_result, ll);
389 struct histogram *histogram;
392 histogram = result->metrics[v].histogram;
393 if (histogram == NULL)
395 /* Probably all values are SYSMIS. */
399 ds_init_empty (&str);
400 ds_put_format (&str, "%s ", var_get_name (dependent_var[v]));
402 factor_to_string (fctr, result, &str);
404 moments1_calculate (result->metrics[v].moments,
405 &n, &mean, &var, NULL, NULL);
406 chart_item_submit (histogram_chart_create (histogram->gsl_hist,
407 ds_cstr (&str), n, mean,
418 show_boxplot_groups (const struct variable **dependent_var,
420 const struct xfactor *fctr)
424 for (v = 0; v < n_dep_var; ++v)
426 const struct factor_result *result;
427 struct boxplot *boxplot;
428 double y_min = DBL_MAX;
429 double y_max = -DBL_MAX;
432 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
434 struct factor_metrics *metrics = &result->metrics[v];
435 const struct ll_list *max_list = extrema_list (metrics->maxima);
436 const struct ll_list *min_list = extrema_list (metrics->minima);
437 const struct extremum *max, *min;
439 if ( ll_is_empty (max_list))
441 msg (MW, _("Not creating plot because data set is empty."));
445 max = ll_data (ll_head(max_list), struct extremum, ll);
446 min = ll_data (ll_head (min_list), struct extremum, ll);
448 y_max = MAX (y_max, max->value);
449 y_min = MIN (y_min, min->value);
452 if (fctr->indep_var[0])
453 title = xasprintf (_("Boxplot of %s vs. %s"),
454 var_to_string (dependent_var[v]),
455 var_to_string (fctr->indep_var[0]));
457 title = xasprintf (_("Boxplot of %s"),
458 var_to_string (dependent_var[v]));
459 boxplot = boxplot_create (y_min, y_max, title);
462 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
464 struct factor_metrics *metrics = &result->metrics[v];
465 struct string str = DS_EMPTY_INITIALIZER;
466 factor_to_string_concise (fctr, result, &str);
467 boxplot_add_box (boxplot, metrics->box_whisker, ds_cstr (&str));
468 metrics->box_whisker = NULL;
472 boxplot_submit (boxplot);
479 show_boxplot_variables (const struct variable **dependent_var,
481 const struct xfactor *fctr
485 const struct factor_result *result;
488 ll_for_each (result, struct factor_result, ll, &fctr->result_list)
491 double y_min = DBL_MAX;
492 double y_max = -DBL_MAX;
493 struct boxplot *boxplot;
495 for (v = 0; v < n_dep_var; ++v)
497 const struct factor_metrics *metrics = &result->metrics[v];
498 const struct ll *max_ll = ll_head (extrema_list (metrics->maxima));
499 const struct ll *min_ll = ll_head (extrema_list (metrics->minima));
500 const struct extremum *max = ll_data (max_ll, struct extremum, ll);
501 const struct extremum *min = ll_data (min_ll, struct extremum, ll);
503 y_max = MAX (y_max, max->value);
504 y_min = MIN (y_min, min->value);
507 ds_init_empty (&title);
508 factor_to_string (fctr, result, &title);
509 boxplot = boxplot_create (y_min, y_max, ds_cstr (&title));
512 for (v = 0; v < n_dep_var; ++v)
514 struct factor_metrics *metrics = &result->metrics[v];
515 boxplot_add_box (boxplot, metrics->box_whisker,
516 var_get_name (dependent_var[v]));
517 metrics->box_whisker = NULL;
520 boxplot_submit (boxplot);
525 /* Show all the appropriate tables */
527 output_examine (const struct dictionary *dict)
531 show_summary (dependent_vars, n_dependent_vars, dict, &level0_factor);
533 if ( cmd.a_statistics[XMN_ST_EXTREME] )
534 show_extremes (dependent_vars, n_dependent_vars, &level0_factor);
536 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
537 show_descriptives (dependent_vars, n_dependent_vars, &level0_factor);
539 if ( cmd.sbc_percentiles)
540 show_percentiles (dependent_vars, n_dependent_vars, &level0_factor);
544 if (cmd.a_plot[XMN_PLT_BOXPLOT])
545 show_boxplot_groups (dependent_vars, n_dependent_vars, &level0_factor);
547 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
548 show_histogram (dependent_vars, n_dependent_vars, &level0_factor);
550 if (cmd.a_plot[XMN_PLT_NPPLOT])
551 show_npplot (dependent_vars, n_dependent_vars, &level0_factor);
554 for (ll = ll_head (&factor_list);
555 ll != ll_null (&factor_list); ll = ll_next (ll))
557 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
558 show_summary (dependent_vars, n_dependent_vars, dict, factor);
560 if ( cmd.a_statistics[XMN_ST_EXTREME] )
561 show_extremes (dependent_vars, n_dependent_vars, factor);
563 if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
564 show_descriptives (dependent_vars, n_dependent_vars, factor);
566 if ( cmd.sbc_percentiles)
567 show_percentiles (dependent_vars, n_dependent_vars, factor);
569 if (cmd.a_plot[XMN_PLT_BOXPLOT])
571 if (cmd.cmp == XMN_GROUPS)
572 show_boxplot_groups (dependent_vars, n_dependent_vars, factor);
573 else if (cmd.cmp == XMN_VARIABLES)
574 show_boxplot_variables (dependent_vars, n_dependent_vars, factor);
577 if (cmd.a_plot[XMN_PLT_HISTOGRAM])
578 show_histogram (dependent_vars, n_dependent_vars, factor);
580 if (cmd.a_plot[XMN_PLT_NPPLOT])
581 show_npplot (dependent_vars, n_dependent_vars, factor);
585 /* Parse the PERCENTILES subcommand */
587 xmn_custom_percentiles (struct lexer *lexer, struct dataset *ds UNUSED,
588 struct cmd_examine *p UNUSED, void *aux UNUSED)
590 lex_match (lexer, T_EQUALS);
592 lex_match (lexer, T_LPAREN);
594 while ( lex_is_number (lexer) )
596 subc_list_double_push (&percentile_list, lex_number (lexer));
600 lex_match (lexer, T_COMMA) ;
602 lex_match (lexer, T_RPAREN);
604 lex_match (lexer, T_EQUALS);
606 if ( lex_match_id (lexer, "HAVERAGE"))
607 percentile_algorithm = PC_HAVERAGE;
609 else if ( lex_match_id (lexer, "WAVERAGE"))
610 percentile_algorithm = PC_WAVERAGE;
612 else if ( lex_match_id (lexer, "ROUND"))
613 percentile_algorithm = PC_ROUND;
615 else if ( lex_match_id (lexer, "EMPIRICAL"))
616 percentile_algorithm = PC_EMPIRICAL;
618 else if ( lex_match_id (lexer, "AEMPIRICAL"))
619 percentile_algorithm = PC_AEMPIRICAL;
621 else if ( lex_match_id (lexer, "NONE"))
622 percentile_algorithm = PC_NONE;
625 if ( 0 == subc_list_double_count (&percentile_list))
627 subc_list_double_push (&percentile_list, 5);
628 subc_list_double_push (&percentile_list, 10);
629 subc_list_double_push (&percentile_list, 25);
630 subc_list_double_push (&percentile_list, 50);
631 subc_list_double_push (&percentile_list, 75);
632 subc_list_double_push (&percentile_list, 90);
633 subc_list_double_push (&percentile_list, 95);
639 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
641 xmn_custom_total (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
642 struct cmd_examine *p, void *aux UNUSED)
644 if ( p->sbc_nototal )
646 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
654 xmn_custom_nototal (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
655 struct cmd_examine *p, void *aux UNUSED)
659 msg (SE, _("%s and %s are mutually exclusive"), "TOTAL", "NOTOTAL");
668 /* Parser for the variables sub command
669 Returns 1 on success */
671 xmn_custom_variables (struct lexer *lexer, struct dataset *ds,
672 struct cmd_examine *cmd,
675 const struct dictionary *dict = dataset_dict (ds);
676 lex_match (lexer, T_EQUALS);
678 if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokcstr (lexer)) == NULL)
679 && lex_token (lexer) != T_ALL)
684 if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars,
685 PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
687 free (dependent_vars);
691 assert (n_dependent_vars);
694 if ( lex_match (lexer, T_BY))
697 success = examine_parse_independent_vars (lexer, dict, cmd);
700 free (dependent_vars);
710 /* Parse the clause specifying the factors */
712 examine_parse_independent_vars (struct lexer *lexer,
713 const struct dictionary *dict,
714 struct cmd_examine *cmd)
717 struct xfactor *sf = xmalloc (sizeof *sf);
719 ll_init (&sf->result_list);
721 if ( (lex_token (lexer) != T_ID ||
722 dict_lookup_var (dict, lex_tokcstr (lexer)) == NULL)
723 && lex_token (lexer) != T_ALL)
729 sf->indep_var[0] = parse_variable (lexer, dict);
730 sf->indep_var[1] = NULL;
732 if ( lex_token (lexer) == T_BY )
734 lex_match (lexer, T_BY);
736 if ( (lex_token (lexer) != T_ID ||
737 dict_lookup_var (dict, lex_tokcstr (lexer)) == NULL)
738 && lex_token (lexer) != T_ALL)
744 sf->indep_var[1] = parse_variable (lexer, dict);
746 ll_push_tail (&factor_list, &sf->ll);
749 ll_push_tail (&factor_list, &sf->ll);
751 lex_match (lexer, T_COMMA);
753 if ( lex_token (lexer) == T_ENDCMD || lex_token (lexer) == T_SLASH )
756 success = examine_parse_independent_vars (lexer, dict, cmd);
765 examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
766 const struct dictionary *dict, struct xfactor *factor)
769 const struct variable *wv = dict_get_weight (dict);
772 struct factor_result *result = xzalloc (sizeof (*result));
775 for (i = 0; i < 2; i++)
776 if (factor->indep_var[i])
777 value_init (&result->value[i], var_get_width (factor->indep_var[i]));
779 result->metrics = xcalloc (n_dependent_vars, sizeof (*result->metrics));
781 if ( cmd->a_statistics[XMN_ST_EXTREME] )
782 n_extrema = cmd->st_n;
785 c = casereader_peek (reader, 0);
789 for (i = 0; i < 2; i++)
790 if (factor->indep_var[i])
791 value_copy (&result->value[i], case_data (c, factor->indep_var[i]),
792 var_get_width (factor->indep_var[i]));
796 for (v = 0; v < n_dependent_vars; ++v)
798 struct casewriter *writer;
799 struct casereader *input = casereader_clone (reader);
801 result->metrics[v].moments = moments1_create (MOMENT_KURTOSIS);
802 result->metrics[v].minima = extrema_create (n_extrema, EXTREME_MINIMA);
803 result->metrics[v].maxima = extrema_create (n_extrema, EXTREME_MAXIMA);
804 result->metrics[v].cmin = DBL_MAX;
806 if (cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
807 cmd->a_plot[XMN_PLT_BOXPLOT] ||
808 cmd->a_plot[XMN_PLT_NPPLOT] ||
809 cmd->sbc_percentiles)
811 /* In this case, we need to sort the data, so we create a sorting
813 struct subcase up_ordering;
814 subcase_init_var (&up_ordering, dependent_vars[v], SC_ASCEND);
815 writer = sort_create_writer (&up_ordering,
816 casereader_get_proto (reader));
817 subcase_destroy (&up_ordering);
821 /* but in this case, sorting is unnecessary, so an ordinary
822 casewriter is sufficient */
824 autopaging_writer_create (casereader_get_proto (reader));
828 /* Sort or just iterate, whilst calculating moments etc */
829 while ((c = casereader_read (input)) != NULL)
831 int n_vals = caseproto_get_n_widths (casereader_get_proto (reader));
832 const casenumber loc = case_data_idx (c, n_vals - 1)->f;
834 const double weight = wv ? case_data (c, wv)->f : 1.0;
835 const union value *value = case_data (c, dependent_vars[v]);
837 if (weight != SYSMIS)
838 minimize (&result->metrics[v].cmin, weight);
840 moments1_add (result->metrics[v].moments,
844 result->metrics[v].n += weight;
846 if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
847 result->metrics[v].n_valid += weight;
849 extrema_add (result->metrics[v].maxima,
854 extrema_add (result->metrics[v].minima,
859 casewriter_write (writer, c);
861 casereader_destroy (input);
862 result->metrics[v].up_reader = casewriter_make_reader (writer);
865 /* If percentiles or descriptives have been requested, then a
866 second pass through the data (which has now been sorted)
868 if ( cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
869 cmd->a_plot[XMN_PLT_BOXPLOT] ||
870 cmd->a_plot[XMN_PLT_NPPLOT] ||
871 cmd->sbc_percentiles)
873 for (v = 0; v < n_dependent_vars; ++v)
877 struct order_stats **os ;
878 struct factor_metrics *metric = &result->metrics[v];
880 metric->n_ptiles = percentile_list.n_data;
882 metric->ptl = xcalloc (metric->n_ptiles, sizeof *metric->ptl);
884 metric->quartiles = xcalloc (3, sizeof (*metric->quartiles));
886 for (i = 0 ; i < metric->n_ptiles; ++i)
888 metric->ptl[i] = percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
890 if ( percentile_list.data[i] == 25)
891 metric->quartiles[0] = metric->ptl[i];
892 else if ( percentile_list.data[i] == 50)
893 metric->quartiles[1] = metric->ptl[i];
894 else if ( percentile_list.data[i] == 75)
895 metric->quartiles[2] = metric->ptl[i];
898 metric->tukey_hinges = tukey_hinges_create (metric->n_valid, metric->cmin);
899 metric->trimmed_mean = trimmed_mean_create (metric->n_valid, 0.05);
901 n_os = metric->n_ptiles + 2;
903 if ( cmd->a_plot[XMN_PLT_NPPLOT] )
906 moments1_calculate (metric->moments,
907 &n, &mean, &var, NULL, NULL);
909 metric->np = np_create (n, mean, var);
913 os = xcalloc (n_os, sizeof *os);
915 for (i = 0 ; i < metric->n_ptiles ; ++i )
917 os[i] = &metric->ptl[i]->parent;
920 os[i] = &metric->tukey_hinges->parent;
921 os[i+1] = &metric->trimmed_mean->parent;
923 if (cmd->a_plot[XMN_PLT_NPPLOT])
924 os[i+2] = &metric->np->parent;
926 order_stats_accumulate (os, n_os,
927 casereader_clone (metric->up_reader),
928 wv, dependent_vars[v], MV_ANY);
933 /* FIXME: Do this in the above loop */
934 if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
937 struct casereader *input = casereader_clone (reader);
939 for (v = 0; v < n_dependent_vars; ++v)
941 const struct extremum *max, *min;
942 struct factor_metrics *metric = &result->metrics[v];
944 const struct ll_list *max_list =
945 extrema_list (result->metrics[v].maxima);
947 const struct ll_list *min_list =
948 extrema_list (result->metrics[v].minima);
950 if ( ll_is_empty (max_list))
952 msg (MW, _("Not creating plot because data set is empty."));
956 assert (! ll_is_empty (min_list));
958 max = (const struct extremum *)
959 ll_data (ll_head(max_list), struct extremum, ll);
961 min = (const struct extremum *)
962 ll_data (ll_head (min_list), struct extremum, ll);
964 metric->histogram = histogram_create (10, min->value, max->value);
967 while ((c = casereader_read (input)) != NULL)
969 const double weight = wv ? case_data (c, wv)->f : 1.0;
971 for (v = 0; v < n_dependent_vars; ++v)
973 struct factor_metrics *metric = &result->metrics[v];
974 if ( metric->histogram)
975 histogram_add (metric->histogram,
976 case_data (c, dependent_vars[v])->f, weight);
980 casereader_destroy (input);
983 /* In this case, a third iteration is required */
984 if (cmd->a_plot[XMN_PLT_BOXPLOT])
986 for (v = 0; v < n_dependent_vars; ++v)
988 struct factor_metrics *metric = &result->metrics[v];
989 int n_vals = caseproto_get_n_widths (casereader_get_proto (
991 struct order_stats *os;
993 metric->box_whisker =
994 box_whisker_create ( metric->tukey_hinges, cmd->v_id, n_vals - 1);
996 os = &metric->box_whisker->parent;
997 order_stats_accumulate ( &os, 1,
998 casereader_clone (metric->up_reader),
999 wv, dependent_vars[v], MV_ANY);
1003 ll_push_tail (&factor->result_list, &result->ll);
1004 casereader_destroy (reader);
1009 run_examine (struct cmd_examine *cmd, struct casereader *input,
1013 const struct dictionary *dict = dataset_dict (ds);
1015 struct casereader *level0 = casereader_clone (input);
1017 c = casereader_peek (input, 0);
1020 casereader_destroy (input);
1024 output_split_file_values (ds, c);
1027 ll_init (&level0_factor.result_list);
1029 examine_group (cmd, level0, 0, dict, &level0_factor);
1031 for (ll = ll_head (&factor_list);
1032 ll != ll_null (&factor_list);
1035 struct xfactor *factor = ll_data (ll, struct xfactor, ll);
1037 struct casereader *group = NULL;
1038 struct casereader *level1;
1039 struct casegrouper *grouper1 = NULL;
1041 level1 = casereader_clone (input);
1042 level1 = sort_execute_1var (level1, factor->indep_var[0]);
1043 grouper1 = casegrouper_create_vars (level1, &factor->indep_var[0], 1);
1045 while (casegrouper_get_next_group (grouper1, &group))
1047 struct casereader *group_copy = casereader_clone (group);
1049 if ( !factor->indep_var[1])
1050 examine_group (cmd, group_copy, 1, dict, factor);
1054 struct casereader *group2 = NULL;
1055 struct casegrouper *grouper2 = NULL;
1057 group_copy = sort_execute_1var (group_copy,
1058 factor->indep_var[1]);
1060 grouper2 = casegrouper_create_vars (group_copy,
1061 &factor->indep_var[1], 1);
1063 while (casegrouper_get_next_group (grouper2, &group2))
1065 examine_group (cmd, group2, 2, dict, factor);
1068 casegrouper_destroy (grouper2);
1071 casereader_destroy (group);
1073 casegrouper_destroy (grouper1);
1076 casereader_destroy (input);
1078 output_examine (dict);
1080 factor_destroy (&level0_factor);
1084 for (ll = ll_head (&factor_list);
1085 ll != ll_null (&factor_list);
1088 struct xfactor *f = ll_data (ll, struct xfactor, ll);
1097 show_summary (const struct variable **dependent_var, int n_dep_var,
1098 const struct dictionary *dict,
1099 const struct xfactor *fctr)
1101 const struct variable *wv = dict_get_weight (dict);
1102 const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
1104 static const char *subtitle[]=
1112 int heading_columns = 1;
1114 const int heading_rows = 3;
1115 struct tab_table *tbl;
1122 if ( fctr->indep_var[0] )
1124 heading_columns = 2;
1126 if ( fctr->indep_var[1] )
1128 heading_columns = 3;
1132 n_rows *= ll_count (&fctr->result_list);
1133 n_rows += heading_rows;
1135 n_cols = heading_columns + 6;
1137 tbl = tab_create (n_cols, n_rows);
1138 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1140 /* Outline the box */
1145 n_cols - 1, n_rows - 1);
1147 /* Vertical lines for the data only */
1152 n_cols - 1, n_rows - 1);
1155 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1156 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, 1 );
1157 tab_hline (tbl, TAL_1, heading_columns, n_cols - 1, heading_rows -1 );
1159 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1162 tab_title (tbl, _("Case Processing Summary"));
1164 tab_joint_text (tbl, heading_columns, 0,
1166 TAB_CENTER | TAT_TITLE,
1169 /* Remove lines ... */
1176 for (j = 0 ; j < 3 ; ++j)
1178 tab_text (tbl, heading_columns + j * 2 , 2, TAB_CENTER | TAT_TITLE,
1181 tab_text (tbl, heading_columns + j * 2 + 1, 2, TAB_CENTER | TAT_TITLE,
1184 tab_joint_text (tbl, heading_columns + j * 2 , 1,
1185 heading_columns + j * 2 + 1, 1,
1186 TAB_CENTER | TAT_TITLE,
1189 tab_box (tbl, -1, -1,
1191 heading_columns + j * 2, 1,
1192 heading_columns + j * 2 + 1, 1);
1196 /* Titles for the independent variables */
1197 if ( fctr->indep_var[0] )
1199 tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1200 var_to_string (fctr->indep_var[0]));
1202 if ( fctr->indep_var[1] )
1204 tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
1205 var_to_string (fctr->indep_var[1]));
1209 for (v = 0 ; v < n_dep_var ; ++v)
1213 const union value *last_value = NULL;
1216 tab_hline (tbl, TAL_1, 0, n_cols -1 ,
1217 v * ll_count (&fctr->result_list)
1222 v * ll_count (&fctr->result_list) + heading_rows,
1223 TAB_LEFT | TAT_TITLE,
1224 var_to_string (dependent_var[v])
1228 for (ll = ll_head (&fctr->result_list);
1229 ll != ll_null (&fctr->result_list); ll = ll_next (ll))
1232 const struct factor_result *result =
1233 ll_data (ll, struct factor_result, ll);
1235 if ( fctr->indep_var[0] )
1238 if ( last_value == NULL ||
1239 !value_equal (last_value, &result->value[0],
1240 var_get_width (fctr->indep_var[0])))
1244 last_value = &result->value[0];
1245 ds_init_empty (&str);
1247 var_append_value_name (fctr->indep_var[0], &result->value[0],
1252 v * ll_count (&fctr->result_list),
1253 TAB_LEFT | TAT_TITLE,
1258 if ( fctr->indep_var[1] && j > 0)
1259 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1261 v * ll_count (&fctr->result_list));
1264 if ( fctr->indep_var[1])
1268 ds_init_empty (&str);
1270 var_append_value_name (fctr->indep_var[1],
1271 &result->value[1], &str);
1275 v * ll_count (&fctr->result_list),
1276 TAB_LEFT | TAT_TITLE,
1284 moments1_calculate (result->metrics[v].moments,
1285 &n, &result->metrics[v].mean,
1286 &result->metrics[v].variance,
1287 &result->metrics[v].skewness,
1288 &result->metrics[v].kurtosis);
1290 result->metrics[v].se_mean = sqrt (result->metrics[v].variance / n) ;
1293 tab_double (tbl, heading_columns,
1294 heading_rows + j + v * ll_count (&fctr->result_list),
1298 tab_text_format (tbl, heading_columns + 1,
1299 heading_rows + j + v * ll_count (&fctr->result_list),
1301 "%g%%", n * 100.0 / result->metrics[v].n);
1304 tab_double (tbl, heading_columns + 2,
1305 heading_rows + j + v * ll_count (&fctr->result_list),
1307 result->metrics[v].n - n,
1310 tab_text_format (tbl, heading_columns + 3,
1311 heading_rows + j + v * ll_count (&fctr->result_list),
1314 (result->metrics[v].n - n) * 100.0 / result->metrics[v].n
1317 /* Total Valid + Missing */
1318 tab_double (tbl, heading_columns + 4,
1319 heading_rows + j + v * ll_count (&fctr->result_list),
1321 result->metrics[v].n,
1324 tab_text_format (tbl, heading_columns + 5,
1325 heading_rows + j + v * ll_count (&fctr->result_list),
1328 ((result->metrics[v].n) * 100.0
1329 / result->metrics[v].n));
1339 #define DESCRIPTIVE_ROWS 13
1342 show_descriptives (const struct variable **dependent_var,
1344 const struct xfactor *fctr)
1347 int heading_columns = 3;
1349 const int heading_rows = 1;
1350 struct tab_table *tbl;
1357 if ( fctr->indep_var[0] )
1359 heading_columns = 4;
1361 if ( fctr->indep_var[1] )
1363 heading_columns = 5;
1367 n_rows *= ll_count (&fctr->result_list) * DESCRIPTIVE_ROWS;
1368 n_rows += heading_rows;
1370 n_cols = heading_columns + 2;
1372 tbl = tab_create (n_cols, n_rows);
1373 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1375 /* Outline the box */
1380 n_cols - 1, n_rows - 1);
1383 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1384 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1386 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1389 if ( fctr->indep_var[0])
1390 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1392 if ( fctr->indep_var[1])
1393 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1395 for (v = 0 ; v < n_dep_var ; ++v )
1400 const int row_var_start =
1401 v * DESCRIPTIVE_ROWS * ll_count(&fctr->result_list);
1405 heading_rows + row_var_start,
1406 TAB_LEFT | TAT_TITLE,
1407 var_to_string (dependent_var[v])
1410 for (ll = ll_head (&fctr->result_list);
1411 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1413 const struct factor_result *result =
1414 ll_data (ll, struct factor_result, ll);
1417 gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0) / 2.0,
1418 result->metrics[v].n - 1);
1420 if ( i > 0 || v > 0 )
1422 const int left_col = (i == 0) ? 0 : 1;
1423 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1424 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS);
1427 if ( fctr->indep_var[0])
1430 ds_init_empty (&vstr);
1431 var_append_value_name (fctr->indep_var[0],
1432 &result->value[0], &vstr);
1435 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1444 tab_text (tbl, n_cols - 4,
1445 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1449 tab_text_format (tbl, n_cols - 4,
1450 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1452 _("%g%% Confidence Interval for Mean"),
1453 cmd.n_cinterval[0]);
1455 tab_text (tbl, n_cols - 3,
1456 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1460 tab_text (tbl, n_cols - 3,
1461 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1465 tab_text (tbl, n_cols - 4,
1466 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1467 TAB_LEFT, _("5% Trimmed Mean"));
1469 tab_text (tbl, n_cols - 4,
1470 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1474 tab_text (tbl, n_cols - 4,
1475 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1479 tab_text (tbl, n_cols - 4,
1480 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1482 _("Std. Deviation"));
1484 tab_text (tbl, n_cols - 4,
1485 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1489 tab_text (tbl, n_cols - 4,
1490 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1494 tab_text (tbl, n_cols - 4,
1495 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1499 tab_text (tbl, n_cols - 4,
1500 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1502 _("Interquartile Range"));
1505 tab_text (tbl, n_cols - 4,
1506 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1510 tab_text (tbl, n_cols - 4,
1511 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1516 /* Now the statistics ... */
1518 tab_double (tbl, n_cols - 2,
1519 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1521 result->metrics[v].mean,
1524 tab_double (tbl, n_cols - 1,
1525 heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
1527 result->metrics[v].se_mean,
1531 tab_double (tbl, n_cols - 2,
1532 heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
1534 result->metrics[v].mean - t *
1535 result->metrics[v].se_mean,
1538 tab_double (tbl, n_cols - 2,
1539 heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
1541 result->metrics[v].mean + t *
1542 result->metrics[v].se_mean,
1546 tab_double (tbl, n_cols - 2,
1547 heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
1549 trimmed_mean_calculate (result->metrics[v].trimmed_mean),
1553 tab_double (tbl, n_cols - 2,
1554 heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
1556 percentile_calculate (result->metrics[v].quartiles[1], percentile_algorithm),
1560 tab_double (tbl, n_cols - 2,
1561 heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
1563 result->metrics[v].variance,
1566 tab_double (tbl, n_cols - 2,
1567 heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
1569 sqrt (result->metrics[v].variance),
1572 tab_double (tbl, n_cols - 2,
1573 heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
1575 percentile_calculate (result->metrics[v].quartiles[2],
1576 percentile_algorithm) -
1577 percentile_calculate (result->metrics[v].quartiles[0],
1578 percentile_algorithm),
1582 tab_double (tbl, n_cols - 2,
1583 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1585 result->metrics[v].skewness,
1588 tab_double (tbl, n_cols - 2,
1589 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1591 result->metrics[v].kurtosis,
1594 tab_double (tbl, n_cols - 1,
1595 heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
1597 calc_seskew (result->metrics[v].n),
1600 tab_double (tbl, n_cols - 1,
1601 heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
1603 calc_sekurt (result->metrics[v].n),
1607 struct extremum *minimum, *maximum ;
1609 struct ll *max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1610 struct ll *min_ll = ll_head (extrema_list (result->metrics[v].minima));
1612 maximum = ll_data (max_ll, struct extremum, ll);
1613 minimum = ll_data (min_ll, struct extremum, ll);
1615 tab_double (tbl, n_cols - 2,
1616 heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
1621 tab_double (tbl, n_cols - 2,
1622 heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
1627 tab_double (tbl, n_cols - 2,
1628 heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
1630 maximum->value - minimum->value,
1636 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1638 tab_title (tbl, _("Descriptives"));
1640 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1643 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1652 show_extremes (const struct variable **dependent_var,
1654 const struct xfactor *fctr)
1657 int heading_columns = 3;
1659 const int heading_rows = 1;
1660 struct tab_table *tbl;
1667 if ( fctr->indep_var[0] )
1669 heading_columns = 4;
1671 if ( fctr->indep_var[1] )
1673 heading_columns = 5;
1677 n_rows *= ll_count (&fctr->result_list) * cmd.st_n * 2;
1678 n_rows += heading_rows;
1680 n_cols = heading_columns + 2;
1682 tbl = tab_create (n_cols, n_rows);
1683 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1685 /* Outline the box */
1690 n_cols - 1, n_rows - 1);
1693 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1694 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1695 tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
1697 if ( fctr->indep_var[0])
1698 tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1700 if ( fctr->indep_var[1])
1701 tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1703 for (v = 0 ; v < n_dep_var ; ++v )
1707 const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
1711 heading_rows + row_var_start,
1712 TAB_LEFT | TAT_TITLE,
1713 var_to_string (dependent_var[v])
1716 for (ll = ll_head (&fctr->result_list);
1717 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1722 const int row_result_start = i * cmd.st_n * 2;
1724 const struct factor_result *result =
1725 ll_data (ll, struct factor_result, ll);
1728 tab_hline (tbl, TAL_1, 1, n_cols - 1,
1729 heading_rows + row_var_start + row_result_start);
1731 tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
1732 heading_rows + row_var_start + row_result_start + cmd.st_n);
1734 for ( e = 1; e <= cmd.st_n; ++e )
1736 tab_text_format (tbl, n_cols - 3,
1737 heading_rows + row_var_start + row_result_start + e - 1,
1741 tab_text_format (tbl, n_cols - 3,
1742 heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
1748 min_ll = ll_head (extrema_list (result->metrics[v].minima));
1749 for (e = 0; e < cmd.st_n;)
1751 struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
1752 double weight = minimum->weight;
1754 while (weight-- > 0 && e < cmd.st_n)
1756 tab_double (tbl, n_cols - 1,
1757 heading_rows + row_var_start + row_result_start + cmd.st_n + e,
1763 tab_fixed (tbl, n_cols - 2,
1764 heading_rows + row_var_start +
1765 row_result_start + cmd.st_n + e,
1772 min_ll = ll_next (min_ll);
1775 max_ll = ll_head (extrema_list (result->metrics[v].maxima));
1776 for (e = 0; e < cmd.st_n;)
1778 struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
1779 double weight = maximum->weight;
1781 while (weight-- > 0 && e < cmd.st_n)
1783 tab_double (tbl, n_cols - 1,
1784 heading_rows + row_var_start +
1785 row_result_start + e,
1791 tab_fixed (tbl, n_cols - 2,
1792 heading_rows + row_var_start +
1793 row_result_start + e,
1800 max_ll = ll_next (max_ll);
1804 if ( fctr->indep_var[0])
1807 ds_init_empty (&vstr);
1808 var_append_value_name (fctr->indep_var[0],
1809 &result->value[0], &vstr);
1812 heading_rows + row_var_start + row_result_start,
1821 tab_text (tbl, n_cols - 4,
1822 heading_rows + row_var_start + row_result_start,
1826 tab_text (tbl, n_cols - 4,
1827 heading_rows + row_var_start + row_result_start + cmd.st_n,
1833 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1836 tab_title (tbl, _("Extreme Values"));
1839 tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
1843 tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
1849 #define PERCENTILE_ROWS 2
1852 show_percentiles (const struct variable **dependent_var,
1854 const struct xfactor *fctr)
1858 int heading_columns = 2;
1860 const int n_percentiles = subc_list_double_count (&percentile_list);
1861 const int heading_rows = 2;
1862 struct tab_table *tbl;
1869 if ( fctr->indep_var[0] )
1871 heading_columns = 3;
1873 if ( fctr->indep_var[1] )
1875 heading_columns = 4;
1879 n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
1880 n_rows += heading_rows;
1882 n_cols = heading_columns + n_percentiles;
1884 tbl = tab_create (n_cols, n_rows);
1885 tab_headers (tbl, heading_columns, 0, heading_rows, 0);
1887 /* Outline the box */
1892 n_cols - 1, n_rows - 1);
1895 tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
1896 tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
1898 if ( fctr->indep_var[0])
1899 tab_text (tbl, 1, 1, TAT_TITLE, var_to_string (fctr->indep_var[0]));
1901 if ( fctr->indep_var[1])
1902 tab_text (tbl, 2, 1, TAT_TITLE, var_to_string (fctr->indep_var[1]));
1904 for (v = 0 ; v < n_dep_var ; ++v )
1910 const int row_var_start =
1911 v * PERCENTILE_ROWS * ll_count(&fctr->result_list);
1915 heading_rows + row_var_start,
1916 TAB_LEFT | TAT_TITLE,
1917 var_to_string (dependent_var[v])
1920 for (ll = ll_head (&fctr->result_list);
1921 ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
1924 const struct factor_result *result =
1925 ll_data (ll, struct factor_result, ll);
1927 if ( i > 0 || v > 0 )
1929 const int left_col = (i == 0) ? 0 : 1;
1930 tab_hline (tbl, TAL_1, left_col, n_cols - 1,
1931 heading_rows + row_var_start + i * PERCENTILE_ROWS);
1934 if ( fctr->indep_var[0])
1937 ds_init_empty (&vstr);
1938 var_append_value_name (fctr->indep_var[0],
1939 &result->value[0], &vstr);
1942 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1951 tab_text (tbl, n_cols - n_percentiles - 1,
1952 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1954 ptile_alg_desc [percentile_algorithm]);
1957 tab_text (tbl, n_cols - n_percentiles - 1,
1958 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1960 _("Tukey's Hinges"));
1963 tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1);
1965 tukey_hinges_calculate (result->metrics[v].tukey_hinges, hinges);
1967 for (j = 0; j < n_percentiles; ++j)
1969 double hinge = SYSMIS;
1970 tab_double (tbl, n_cols - n_percentiles + j,
1971 heading_rows + row_var_start + i * PERCENTILE_ROWS,
1973 percentile_calculate (result->metrics[v].ptl[j],
1974 percentile_algorithm),
1978 if ( result->metrics[v].ptl[j]->ptile == 0.5)
1980 else if ( result->metrics[v].ptl[j]->ptile == 0.25)
1982 else if ( result->metrics[v].ptl[j]->ptile == 0.75)
1985 if ( hinge != SYSMIS)
1986 tab_double (tbl, n_cols - n_percentiles + j,
1987 heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
1997 tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
1999 tab_title (tbl, _("Percentiles"));
2002 for (i = 0 ; i < n_percentiles; ++i )
2004 tab_text_format (tbl, n_cols - n_percentiles + i, 1,
2005 TAB_CENTER | TAT_TITLE,
2007 subc_list_double_at (&percentile_list, i));
2012 tab_joint_text (tbl,
2013 n_cols - n_percentiles, 0,
2015 TAB_CENTER | TAT_TITLE,
2018 /* Vertical lines for the data only */
2022 n_cols - n_percentiles, 1,
2023 n_cols - 1, n_rows - 1);
2025 tab_hline (tbl, TAL_1, n_cols - n_percentiles, n_cols - 1, 1);
2033 factor_to_string_concise (const struct xfactor *fctr,
2034 const struct factor_result *result,
2038 if (fctr->indep_var[0])
2040 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2042 if ( fctr->indep_var[1] )
2044 ds_put_cstr (str, ",");
2046 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2048 ds_put_cstr (str, ")");
2055 factor_to_string (const struct xfactor *fctr,
2056 const struct factor_result *result,
2060 if (fctr->indep_var[0])
2062 ds_put_format (str, "(%s = ", var_get_name (fctr->indep_var[0]));
2064 var_append_value_name (fctr->indep_var[0], &result->value[0], str);
2066 if ( fctr->indep_var[1] )
2068 ds_put_cstr (str, ",");
2069 ds_put_format (str, "%s = ", var_get_name (fctr->indep_var[1]));
2071 var_append_value_name (fctr->indep_var[1], &result->value[1], str);
2073 ds_put_cstr (str, ")");