45c969d4c00a5edaaeac0fce56ed8721a36cff1f
[pspp] / src / language / stats / frequencies.q
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2007, 2009, 2010 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include <math.h>
20 #include <stdlib.h>
21 #include <gsl/gsl_histogram.h>
22
23 #include <data/case.h>
24 #include <data/casegrouper.h>
25 #include <data/casereader.h>
26 #include <data/dictionary.h>
27 #include <data/format.h>
28 #include <data/procedure.h>
29 #include <data/settings.h>
30 #include <data/value-labels.h>
31 #include <data/variable.h>
32 #include <language/command.h>
33 #include <language/dictionary/split-file.h>
34 #include <language/lexer/lexer.h>
35 #include <libpspp/array.h>
36 #include <libpspp/bit-vector.h>
37 #include <libpspp/compiler.h>
38 #include <libpspp/hash.h>
39 #include <libpspp/message.h>
40 #include <libpspp/misc.h>
41 #include <libpspp/pool.h>
42 #include <libpspp/str.h>
43 #include <math/histogram.h>
44 #include <math/moments.h>
45 #include <output/chart-item.h>
46 #include <output/charts/piechart.h>
47 #include <output/charts/plot-hist.h>
48 #include <output/tab.h>
49
50 #include "freq.h"
51
52 #include "minmax.h"
53 #include "xalloc.h"
54
55 #include "gettext.h"
56 #define _(msgid) gettext (msgid)
57 #define N_(msgid) msgid
58
59 /* (headers) */
60
61 /* (specification)
62    FREQUENCIES (frq_):
63      *+variables=custom;
64      +format=table:limit(n:limit,"%s>0")/notable/!table,
65              sort:!avalue/dvalue/afreq/dfreq;
66      missing=miss:include/!exclude;
67      barchart(ba_)=:minimum(d:min),
68             :maximum(d:max),
69             scale:freq(*n:freq,"%s>0")/percent(*n:pcnt,"%s>0");
70      piechart(pie_)=:minimum(d:min),
71             :maximum(d:max),
72             missing:missing/!nomissing,
73             scale:!freq/percent;
74      histogram(hi_)=:minimum(d:min),
75             :maximum(d:max),
76             scale:freq(*n:freq,"%s>0")/percent(*n:pcnt,"%s>0"),
77             norm:!nonormal/normal;
78      +grouped=custom;
79      +ntiles=integer;
80      +percentiles = double list;
81      +statistics[st_]=mean,semean,median,mode,stddev,variance,
82             kurtosis,skewness,range,minimum,maximum,sum,
83             default,seskewness,sekurtosis,all,none.
84 */
85 /* (declarations) */
86 /* (functions) */
87
88 /* Statistics. */
89 enum
90   {
91     frq_mean = 0, frq_semean, frq_median, frq_mode, frq_stddev, frq_variance,
92     frq_kurt, frq_sekurt, frq_skew, frq_seskew, frq_range, frq_min, frq_max,
93     frq_sum, frq_n_stats
94   };
95
96 /* Description of a statistic. */
97 struct frq_info
98   {
99     int st_indx;                /* Index into a_statistics[]. */
100     const char *s10;            /* Identifying string. */
101   };
102
103 /* Table of statistics, indexed by dsc_*. */
104 static const struct frq_info st_name[frq_n_stats + 1] =
105 {
106   {FRQ_ST_MEAN, N_("Mean")},
107   {FRQ_ST_SEMEAN, N_("S.E. Mean")},
108   {FRQ_ST_MEDIAN, N_("Median")},
109   {FRQ_ST_MODE, N_("Mode")},
110   {FRQ_ST_STDDEV, N_("Std Dev")},
111   {FRQ_ST_VARIANCE, N_("Variance")},
112   {FRQ_ST_KURTOSIS, N_("Kurtosis")},
113   {FRQ_ST_SEKURTOSIS, N_("S.E. Kurt")},
114   {FRQ_ST_SKEWNESS, N_("Skewness")},
115   {FRQ_ST_SESKEWNESS, N_("S.E. Skew")},
116   {FRQ_ST_RANGE, N_("Range")},
117   {FRQ_ST_MINIMUM, N_("Minimum")},
118   {FRQ_ST_MAXIMUM, N_("Maximum")},
119   {FRQ_ST_SUM, N_("Sum")},
120   {-1, 0},
121 };
122
123 /* Percentiles to calculate. */
124
125 struct percentile
126 {
127   double p;        /* the %ile to be calculated */
128   double value;    /* the %ile's value */
129   double x1;       /* The datum value <= the percentile */
130   double x2;       /* The datum value >= the percentile */
131   int flag;
132   int flag2;       /* Set to 1 if this percentile value has been found */
133   bool show;       /* True to show this percentile in the statistics box. */
134 };
135
136
137 static void add_percentile (double x, bool show);
138
139 static struct percentile *percentiles;
140 static int n_percentiles, n_show_percentiles;
141
142 /* Groups of statistics. */
143 #define BI          BIT_INDEX
144 #define frq_default                                                     \
145         (BI (frq_mean) | BI (frq_stddev) | BI (frq_min) | BI (frq_max))
146 #define frq_all                                                 \
147         (BI (frq_sum) | BI(frq_min) | BI(frq_max)               \
148          | BI(frq_mean) | BI(frq_semean) | BI(frq_stddev)       \
149          | BI(frq_variance) | BI(frq_kurt) | BI(frq_sekurt)     \
150          | BI(frq_skew) | BI(frq_seskew) | BI(frq_range)        \
151          | BI(frq_range) | BI(frq_mode) | BI(frq_median))
152
153 /* Statistics; number of statistics. */
154 static unsigned long stats;
155 static int n_stats;
156
157 struct frq_chart
158   {
159     double x_min;               /* X axis minimum value. */
160     double x_max;               /* X axis maximum value. */
161     int y_scale;                /* Y axis scale: FRQ_FREQ or FRQ_PERCENT. */
162
163     /* Histograms only. */
164     double y_max;               /* Y axis maximum value. */
165     bool draw_normal;           /* Whether to draw normal curve. */
166
167     /* Pie charts only. */
168     bool include_missing;       /* Whether to include missing values. */
169   };
170
171 /* Histogram and pie chart settings. */
172 static struct frq_chart hist, pie;
173
174 /* Parsed command. */
175 static struct cmd_frequencies cmd;
176
177 /* Variables for which to calculate statistics. */
178 static size_t n_variables;
179 static const struct variable **v_variables;
180
181 /* Pools. */
182 static struct pool *data_pool;          /* For per-SPLIT FILE group data. */
183 static struct pool *syntax_pool;        /* For syntax-related data. */
184
185 /* Frequency tables. */
186
187 /* Entire frequency table. */
188 struct freq_tab
189   {
190     struct hsh_table *data;     /* Undifferentiated data. */
191     struct freq_mutable *valid; /* Valid freqs. */
192     int n_valid;                /* Number of total freqs. */
193     const struct dictionary *dict; /* The dict from whence entries in the table
194                                       come */
195
196     struct freq_mutable *missing; /* Missing freqs. */
197     int n_missing;              /* Number of missing freqs. */
198
199     /* Statistics. */
200     double total_cases;         /* Sum of weights of all cases. */
201     double valid_cases;         /* Sum of weights of valid cases. */
202   };
203
204 /* Per-variable frequency data. */
205 struct var_freqs
206   {
207     /* Freqency table. */
208     struct freq_tab tab;        /* Frequencies table to use. */
209
210     /* Percentiles. */
211     int n_groups;               /* Number of groups. */
212     double *groups;             /* Groups. */
213
214     /* Statistics. */
215     double stat[frq_n_stats];
216
217     /* Variable attributes. */
218     int width;
219     struct fmt_spec print;
220   };
221
222 static inline struct var_freqs *
223 get_var_freqs (const struct variable *v)
224 {
225   return var_get_aux (v);
226 }
227
228 static void determine_charts (void);
229
230 static void calc_stats (const struct variable *v, double d[frq_n_stats]);
231
232 static void precalc (struct casereader *, struct dataset *);
233 static void calc (const struct ccase *, const struct dataset *);
234 static void postcalc (const struct dataset *);
235
236 static void postprocess_freq_tab (const struct variable *);
237 static void dump_freq_table (const struct variable *, const struct variable *);
238 static void dump_statistics (const struct variable *, const struct variable *);
239 static void cleanup_freq_tab (const struct variable *);
240
241 static hsh_compare_func compare_value_numeric_a, compare_value_alpha_a;
242 static hsh_compare_func compare_value_numeric_d, compare_value_alpha_d;
243 static hsh_compare_func compare_freq_numeric_a, compare_freq_alpha_a;
244 static hsh_compare_func compare_freq_numeric_d, compare_freq_alpha_d;
245
246
247 static void do_piechart(const struct variable *var,
248                         const struct freq_tab *frq_tab);
249
250 struct histogram *
251 freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var);
252
253
254 \f
255 /* Parser and outline. */
256
257 static int internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds);
258
259 int
260 cmd_frequencies (struct lexer *lexer, struct dataset *ds)
261 {
262   int result;
263
264   syntax_pool = pool_create ();
265   result = internal_cmd_frequencies (lexer, ds);
266   pool_destroy (syntax_pool);
267   syntax_pool=0;
268   pool_destroy (data_pool);
269   data_pool=0;
270   free (v_variables);
271   v_variables=0;
272   return result;
273 }
274
275 static int
276 internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds)
277 {
278   struct casegrouper *grouper;
279   struct casereader *input, *group;
280   bool ok;
281   int i;
282
283   n_percentiles = 0;
284   n_show_percentiles = 0;
285   percentiles = NULL;
286
287   n_variables = 0;
288   v_variables = NULL;
289
290   if (!parse_frequencies (lexer, ds, &cmd, NULL))
291     return CMD_FAILURE;
292
293   /* Figure out statistics to calculate. */
294   stats = 0;
295   if (cmd.a_statistics[FRQ_ST_DEFAULT] || !cmd.sbc_statistics)
296     stats |= frq_default;
297   if (cmd.a_statistics[FRQ_ST_ALL])
298     stats |= frq_all;
299   if (cmd.sort != FRQ_AVALUE && cmd.sort != FRQ_DVALUE)
300     stats &= ~BIT_INDEX (frq_median);
301   for (i = 0; i < frq_n_stats; i++)
302     if (cmd.a_statistics[st_name[i].st_indx])
303       stats |= BIT_INDEX (i);
304   if (stats & frq_kurt)
305     stats |= BIT_INDEX (frq_sekurt);
306   if (stats & frq_skew)
307     stats |= BIT_INDEX (frq_seskew);
308
309   /* Calculate n_stats. */
310   n_stats = 0;
311   for (i = 0; i < frq_n_stats; i++)
312     if ((stats & BIT_INDEX (i)))
313       n_stats++;
314
315   /* Charting. */
316   determine_charts ();
317   if (cmd.sbc_histogram || cmd.sbc_piechart || cmd.sbc_ntiles)
318     cmd.sort = FRQ_AVALUE;
319
320   /* Work out what percentiles need to be calculated */
321   if ( cmd.sbc_percentiles )
322     {
323       for ( i = 0 ; i < MAXLISTS ; ++i )
324         {
325           int pl;
326           subc_list_double *ptl_list = &cmd.dl_percentiles[i];
327           for ( pl = 0 ; pl < subc_list_double_count(ptl_list); ++pl)
328             add_percentile (subc_list_double_at(ptl_list, pl) / 100.0, true);
329         }
330     }
331   if ( cmd.sbc_ntiles )
332     {
333       for ( i = 0 ; i < cmd.sbc_ntiles ; ++i )
334         {
335           int j;
336           for (j = 0; j <= cmd.n_ntiles[i]; ++j )
337             add_percentile (j / (double) cmd.n_ntiles[i], true);
338         }
339     }
340   if (stats & BIT_INDEX (frq_median))
341     {
342       /* Treat the median as the 50% percentile.
343          We output it in the percentiles table as "50 (Median)." */
344       add_percentile (0.5, true);
345       stats &= ~BIT_INDEX (frq_median);
346       n_stats--;
347     }
348   if (cmd.sbc_histogram)
349     {
350       add_percentile (0.25, false);
351       add_percentile (0.75, false);
352     }
353
354   /* Do it! */
355   input = casereader_create_filter_weight (proc_open (ds), dataset_dict (ds),
356                                            NULL, NULL);
357   grouper = casegrouper_create_splits (input, dataset_dict (ds));
358   for (; casegrouper_get_next_group (grouper, &group);
359        casereader_destroy (group))
360     {
361       struct ccase *c;
362
363       precalc (group, ds);
364       for (; (c = casereader_read (group)) != NULL; case_unref (c))
365         calc (c, ds);
366       postcalc (ds);
367     }
368   ok = casegrouper_destroy (grouper);
369   ok = proc_commit (ds) && ok;
370
371   free_frequencies(&cmd);
372
373   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
374 }
375
376 /* Figure out which charts the user requested.  */
377 static void
378 determine_charts (void)
379 {
380   if (cmd.sbc_barchart)
381     msg (SW, _("Bar charts are not implemented."));
382
383   if (cmd.sbc_histogram)
384     {
385       hist.x_min = cmd.hi_min;
386       hist.x_max = cmd.hi_max;
387       hist.y_scale = cmd.hi_scale;
388       hist.y_max = cmd.hi_scale == FRQ_FREQ ? cmd.hi_freq : cmd.hi_pcnt;
389       hist.draw_normal = cmd.hi_norm != FRQ_NONORMAL;
390       hist.include_missing = false;
391
392       if (hist.x_min != SYSMIS && hist.x_max != SYSMIS
393           && hist.x_min >= hist.x_max)
394         {
395           msg (SE, _("MAX for histogram must be greater than or equal to MIN, "
396                      "but MIN was specified as %.15g and MAX as %.15g.  "
397                      "MIN and MAX will be ignored."), hist.x_min, hist.x_max);
398           hist.x_min = hist.x_max = SYSMIS;
399         }
400     }
401
402   if (cmd.sbc_piechart)
403     {
404       pie.x_min = cmd.pie_min;
405       pie.x_max = cmd.pie_max;
406       pie.y_scale = cmd.pie_scale;
407       pie.include_missing = cmd.pie_missing == FRQ_MISSING;
408
409       if (pie.x_min != SYSMIS && pie.x_max != SYSMIS
410           && pie.x_min >= pie.x_max)
411         {
412           msg (SE, _("MAX for pie chart must be greater than or equal to MIN, "
413                      "but MIN was specified as %.15g and MAX as %.15g.  "
414                      "MIN and MAX will be ignored."), pie.x_min, pie.x_max);
415           pie.x_min = pie.x_max = SYSMIS;
416         }
417     }
418
419 }
420
421 /* Add data from case C to the frequency table. */
422 static void
423 calc (const struct ccase *c, const struct dataset *ds)
424 {
425   double weight = dict_get_case_weight (dataset_dict (ds), c, NULL);
426   size_t i;
427
428   for (i = 0; i < n_variables; i++)
429     {
430       const struct variable *v = v_variables[i];
431       const union value *val = case_data (c, v);
432       struct var_freqs *vf = get_var_freqs (v);
433       struct freq_tab *ft = &vf->tab;
434
435       struct freq_mutable target;
436       struct freq_mutable **fpp;
437
438       target.value = *val;
439       fpp = (struct freq_mutable **) hsh_probe (ft->data, &target);
440
441       if (*fpp != NULL)
442         (*fpp)->count += weight;
443       else
444         {
445           struct freq_mutable *fp = pool_alloc (data_pool, sizeof *fp);
446           fp->count = weight;
447           value_init_pool (data_pool, &fp->value, vf->width);
448           value_copy (&fp->value, val, vf->width);
449           *fpp = fp;
450         }
451     }
452 }
453
454 /* Prepares each variable that is the target of FREQUENCIES by setting
455    up its hash table. */
456 static void
457 precalc (struct casereader *input, struct dataset *ds)
458 {
459   struct ccase *c;
460   size_t i;
461
462   c = casereader_peek (input, 0);
463   if (c != NULL)
464     {
465       output_split_file_values (ds, c);
466       case_unref (c);
467     }
468
469   pool_destroy (data_pool);
470   data_pool = pool_create ();
471
472   for (i = 0; i < n_variables; i++)
473     {
474       const struct variable *v = v_variables[i];
475       struct freq_tab *ft = &get_var_freqs (v)->tab;
476
477       ft->data = hsh_create (16, compare_freq, hash_freq, NULL, v);
478     }
479 }
480
481 /* Finishes up with the variables after frequencies have been
482    calculated.  Displays statistics, percentiles, ... */
483 static void
484 postcalc (const struct dataset *ds)
485 {
486   const struct dictionary *dict = dataset_dict (ds);
487   const struct variable *wv = dict_get_weight (dict);
488   size_t i;
489
490   for (i = 0; i < n_variables; i++)
491     {
492       const struct variable *v = v_variables[i];
493       struct var_freqs *vf = get_var_freqs (v);
494       struct freq_tab *ft = &vf->tab;
495       int n_categories;
496
497       postprocess_freq_tab (v);
498
499       /* Frequencies tables. */
500       n_categories = ft->n_valid + ft->n_missing;
501       if  (cmd.table == FRQ_TABLE
502            || (cmd.table == FRQ_LIMIT && n_categories <= cmd.limit))
503         dump_freq_table (v, wv);
504
505       /* Statistics. */
506       if (n_stats)
507         dump_statistics (v, wv);
508
509       if (cmd.sbc_histogram && var_is_numeric (v) && ft->n_valid > 0)
510         {
511           double d[frq_n_stats];
512           struct histogram *histogram;
513
514           calc_stats (v, d);
515
516           histogram = freq_tab_to_hist (ft, v);
517
518           chart_item_submit (histogram_chart_create (
519                                histogram->gsl_hist, var_to_string(v),
520                                vf->tab.valid_cases,
521                                d[frq_mean],
522                                d[frq_stddev],
523                                hist.draw_normal));
524
525           statistic_destroy (&histogram->parent);
526         }
527
528       if (cmd.sbc_piechart)
529         do_piechart(v_variables[i], ft);
530
531       cleanup_freq_tab (v);
532
533     }
534 }
535
536 /* Returns the comparison function that should be used for
537    sorting a frequency table by FRQ_SORT using VAL_TYPE
538    values. */
539 static hsh_compare_func *
540 get_freq_comparator (int frq_sort, enum val_type val_type)
541 {
542   bool is_numeric = val_type == VAL_NUMERIC;
543   switch (frq_sort)
544     {
545     case FRQ_AVALUE:
546       return is_numeric ? compare_value_numeric_a : compare_value_alpha_a;
547     case FRQ_DVALUE:
548       return is_numeric ? compare_value_numeric_d : compare_value_alpha_d;
549     case FRQ_AFREQ:
550       return is_numeric ? compare_freq_numeric_a : compare_freq_alpha_a;
551     case FRQ_DFREQ:
552       return is_numeric ? compare_freq_numeric_d : compare_freq_alpha_d;
553     default:
554       NOT_REACHED ();
555     }
556 }
557
558 /* Returns true iff the value in struct freq_mutable F is non-missing
559    for variable V. */
560 static bool
561 not_missing (const void *f_, const void *v_)
562 {
563   const struct freq_mutable *f = f_;
564   const struct variable *v = v_;
565
566   return !var_is_value_missing (v, &f->value, MV_ANY);
567 }
568
569 /* Summarizes the frequency table data for variable V. */
570 static void
571 postprocess_freq_tab (const struct variable *v)
572 {
573   hsh_compare_func *compare;
574   struct freq_tab *ft;
575   size_t count;
576   void *const *data;
577   struct freq_mutable *freqs, *f;
578   size_t i;
579
580   ft = &get_var_freqs (v)->tab;
581   compare = get_freq_comparator (cmd.sort, var_get_type (v));
582
583   /* Extract data from hash table. */
584   count = hsh_count (ft->data);
585   data = hsh_data (ft->data);
586
587   /* Copy dereferenced data into freqs. */
588   freqs = xnmalloc (count, sizeof *freqs);
589   for (i = 0; i < count; i++)
590     {
591       struct freq_mutable *f = data[i];
592       freqs[i] = *f;
593     }
594
595   /* Put data into ft. */
596   ft->valid = freqs;
597   ft->n_valid = partition (freqs, count, sizeof *freqs, not_missing, v);
598   ft->missing = freqs + ft->n_valid;
599   ft->n_missing = count - ft->n_valid;
600
601   /* Sort data. */
602   sort (ft->valid, ft->n_valid, sizeof *ft->valid, compare, v);
603   sort (ft->missing, ft->n_missing, sizeof *ft->missing, compare, v);
604
605   /* Summary statistics. */
606   ft->valid_cases = 0.0;
607   for(i = 0 ;  i < ft->n_valid ; ++i )
608     {
609       f = &ft->valid[i];
610       ft->valid_cases += f->count;
611
612     }
613
614   ft->total_cases = ft->valid_cases ;
615   for(i = 0 ;  i < ft->n_missing ; ++i )
616     {
617       f = &ft->missing[i];
618       ft->total_cases += f->count;
619     }
620
621 }
622
623 /* Frees the frequency table for variable V. */
624 static void
625 cleanup_freq_tab (const struct variable *v)
626 {
627   struct freq_tab *ft = &get_var_freqs (v)->tab;
628   free (ft->valid);
629   hsh_destroy (ft->data);
630 }
631
632 /* Parses the VARIABLES subcommand, adding to
633    {n_variables,v_variables}. */
634 static int
635 frq_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_frequencies *cmd UNUSED, void *aux UNUSED)
636 {
637   size_t old_n_variables = n_variables;
638   size_t i;
639
640   lex_match (lexer, '=');
641   if (lex_token (lexer) != T_ALL && (lex_token (lexer) != T_ID
642                          || dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) == NULL))
643     return 2;
644
645   if (!parse_variables_const (lexer, dataset_dict (ds), &v_variables, &n_variables,
646                         PV_APPEND | PV_NO_SCRATCH))
647     return 0;
648
649   for (i = old_n_variables; i < n_variables; i++)
650     {
651       const struct variable *v = v_variables[i];
652       struct var_freqs *vf;
653
654       if (var_get_aux (v) != NULL)
655         {
656           msg (SE, _("Variable %s specified multiple times on VARIABLES "
657                      "subcommand."), var_get_name (v));
658           return 0;
659         }
660       vf = var_attach_aux (v, xmalloc (sizeof *vf), var_dtor_free);
661       vf->tab.valid = vf->tab.missing = NULL;
662       vf->tab.dict = dataset_dict (ds);
663       vf->n_groups = 0;
664       vf->groups = NULL;
665       vf->width = var_get_width (v);
666       vf->print = *var_get_print_format (v);
667     }
668   return 1;
669 }
670
671 /* Parses the GROUPED subcommand, setting the n_grouped, grouped
672    fields of specified variables. */
673 static int
674 frq_custom_grouped (struct lexer *lexer, struct dataset *ds, struct cmd_frequencies *cmd UNUSED, void *aux UNUSED)
675 {
676   lex_match (lexer, '=');
677   if ((lex_token (lexer) == T_ID && dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL)
678       || lex_token (lexer) == T_ID)
679     for (;;)
680       {
681         size_t i;
682
683         /* Max, current size of list; list itself. */
684         int nl, ml;
685         double *dl;
686
687         /* Variable list. */
688         size_t n;
689         const struct variable **v;
690
691         if (!parse_variables_const (lexer, dataset_dict (ds), &v, &n,
692                               PV_NO_DUPLICATE | PV_NUMERIC))
693           return 0;
694         if (lex_match (lexer, '('))
695           {
696             nl = ml = 0;
697             dl = NULL;
698             while (lex_integer (lexer))
699               {
700                 if (nl >= ml)
701                   {
702                     ml += 16;
703                     dl = pool_nrealloc (syntax_pool, dl, ml, sizeof *dl);
704                   }
705                 dl[nl++] = lex_tokval (lexer);
706                 lex_get (lexer);
707                 lex_match (lexer, ',');
708               }
709             /* Note that nl might still be 0 and dl might still be
710                NULL.  That's okay. */
711             if (!lex_match (lexer, ')'))
712               {
713                 free (v);
714                 msg (SE, _("`)' expected after GROUPED interval list."));
715                 return 0;
716               }
717           }
718         else
719           {
720             nl = 0;
721             dl = NULL;
722           }
723
724         for (i = 0; i < n; i++)
725           if (var_get_aux (v[i]) == NULL)
726             msg (SE, _("Variables %s specified on GROUPED but not on "
727                        "VARIABLES."), var_get_name (v[i]));
728           else
729             {
730               struct var_freqs *vf = get_var_freqs (v[i]);
731
732               if (vf->groups != NULL)
733                 msg (SE, _("Variables %s specified multiple times on GROUPED "
734                            "subcommand."), var_get_name (v[i]));
735               else
736                 {
737                   vf->n_groups = nl;
738                   vf->groups = dl;
739                 }
740             }
741         free (v);
742         if (!lex_match (lexer, '/'))
743           break;
744         if ((lex_token (lexer) != T_ID || dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL)
745             && lex_token (lexer) != T_ALL)
746           {
747             lex_put_back (lexer, '/');
748             break;
749           }
750       }
751
752   return 1;
753 }
754
755 /* Adds X to the list of percentiles, keeping the list in proper
756    order.  If SHOW is true, the percentile will be shown in the statistics
757    box, otherwise it will be hidden. */
758 static void
759 add_percentile (double x, bool show)
760 {
761   int i;
762
763   for (i = 0; i < n_percentiles; i++)
764     {
765       /* Do nothing if it's already in the list */
766       if ( fabs(x - percentiles[i].p) < DBL_EPSILON )
767         {
768           if (show && !percentiles[i].show)
769             {
770               n_show_percentiles++;
771               percentiles[i].show = true;
772             }
773           return;
774         }
775
776       if (x < percentiles[i].p)
777         break;
778     }
779
780   if (i >= n_percentiles || x != percentiles[i].p)
781     {
782       percentiles = pool_nrealloc (syntax_pool, percentiles,
783                                    n_percentiles + 1, sizeof *percentiles);
784       insert_element (percentiles, n_percentiles, sizeof *percentiles, i);
785       percentiles[i].p = x;
786       percentiles[i].show = show;
787       n_percentiles++;
788       if (show)
789         n_show_percentiles++;
790     }
791 }
792
793 /* Comparison functions. */
794
795 /* Ascending numeric compare of values. */
796 static int
797 compare_value_numeric_a (const void *a_, const void *b_, const void *aux UNUSED)
798 {
799   const struct freq_mutable *a = a_;
800   const struct freq_mutable *b = b_;
801
802   if (a->value.f > b->value.f)
803     return 1;
804   else if (a->value.f < b->value.f)
805     return -1;
806   else
807     return 0;
808 }
809
810 /* Ascending string compare of values. */
811 static int
812 compare_value_alpha_a (const void *a_, const void *b_, const void *v_)
813 {
814   const struct freq_mutable *a = a_;
815   const struct freq_mutable *b = b_;
816   const struct variable *v = v_;
817   struct var_freqs *vf = get_var_freqs (v);
818
819   return value_compare_3way (&a->value, &b->value, vf->width);
820 }
821
822 /* Descending numeric compare of values. */
823 static int
824 compare_value_numeric_d (const void *a, const void *b, const void *aux UNUSED)
825 {
826   return -compare_value_numeric_a (a, b, aux);
827 }
828
829 /* Descending string compare of values. */
830 static int
831 compare_value_alpha_d (const void *a, const void *b, const void *v)
832 {
833   return -compare_value_alpha_a (a, b, v);
834 }
835
836 /* Ascending numeric compare of frequency;
837    secondary key on ascending numeric value. */
838 static int
839 compare_freq_numeric_a (const void *a_, const void *b_, const void *aux UNUSED)
840 {
841   const struct freq_mutable *a = a_;
842   const struct freq_mutable *b = b_;
843
844   if (a->count > b->count)
845     return 1;
846   else if (a->count < b->count)
847     return -1;
848
849   if (a->value.f > b->value.f)
850     return 1;
851   else if (a->value.f < b->value.f)
852     return -1;
853   else
854     return 0;
855 }
856
857 /* Ascending numeric compare of frequency;
858    secondary key on ascending string value. */
859 static int
860 compare_freq_alpha_a (const void *a_, const void *b_, const void *v_)
861 {
862   const struct freq_mutable *a = a_;
863   const struct freq_mutable *b = b_;
864   const struct variable *v = v_;
865   struct var_freqs *vf = get_var_freqs (v);
866
867   if (a->count > b->count)
868     return 1;
869   else if (a->count < b->count)
870     return -1;
871   else
872     return value_compare_3way (&a->value, &b->value, vf->width);
873 }
874
875 /* Descending numeric compare of frequency;
876    secondary key on ascending numeric value. */
877 static int
878 compare_freq_numeric_d (const void *a_, const void *b_, const void *aux UNUSED)
879 {
880   const struct freq_mutable *a = a_;
881   const struct freq_mutable *b = b_;
882
883   if (a->count > b->count)
884     return -1;
885   else if (a->count < b->count)
886     return 1;
887
888   if (a->value.f > b->value.f)
889     return 1;
890   else if (a->value.f < b->value.f)
891     return -1;
892   else
893     return 0;
894 }
895
896 /* Descending numeric compare of frequency;
897    secondary key on ascending string value. */
898 static int
899 compare_freq_alpha_d (const void *a_, const void *b_, const void *v_)
900 {
901   const struct freq_mutable *a = a_;
902   const struct freq_mutable *b = b_;
903   const struct variable *v = v_;
904   struct var_freqs *vf = get_var_freqs (v);
905
906   if (a->count > b->count)
907     return -1;
908   else if (a->count < b->count)
909     return 1;
910   else
911     return value_compare_3way (&a->value, &b->value, vf->width);
912 }
913 \f
914 /* Frequency table display. */
915
916 /* Displays a full frequency table for variable V. */
917 static void
918 dump_freq_table (const struct variable *v, const struct variable *wv)
919 {
920   const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : &F_8_0;
921   int n_categories;
922   struct var_freqs *vf;
923   struct freq_tab *ft;
924   struct freq_mutable *f;
925   struct tab_table *t;
926   int r, x;
927   double cum_total = 0.0;
928   double cum_freq = 0.0;
929
930   static const char *headings[] = {
931     N_("Value Label"),
932     N_("Value"),
933     N_("Frequency"),
934     N_("Percent"),
935     N_("Valid Percent"),
936     N_("Cum Percent")
937   };
938
939   vf = get_var_freqs (v);
940   ft = &vf->tab;
941   n_categories = ft->n_valid + ft->n_missing;
942   t = tab_create (6, n_categories + 2);
943   tab_headers (t, 0, 0, 1, 0);
944
945   for (x = 0; x < 6; x++)
946     tab_text (t, x, 0, TAB_CENTER | TAT_TITLE, gettext (headings[x]));
947
948   r = 1;
949   for (f = ft->valid; f < ft->missing; f++)
950     {
951       const char *label;
952       double percent, valid_percent;
953
954       cum_freq += f->count;
955
956       percent = f->count / ft->total_cases * 100.0;
957       valid_percent = f->count / ft->valid_cases * 100.0;
958       cum_total += valid_percent;
959
960       label = var_lookup_value_label (v, &f->value);
961       if (label != NULL)
962         tab_text (t, 0, r, TAB_LEFT, label);
963
964       tab_value (t, 1, r, TAB_NONE, &f->value, ft->dict, &vf->print);
965       tab_double (t, 2, r, TAB_NONE, f->count, wfmt);
966       tab_double (t, 3, r, TAB_NONE, percent, NULL);
967       tab_double (t, 4, r, TAB_NONE, valid_percent, NULL);
968       tab_double (t, 5, r, TAB_NONE, cum_total, NULL);
969       r++;
970     }
971   for (; f < &ft->valid[n_categories]; f++)
972     {
973       const char *label;
974
975       cum_freq += f->count;
976
977       label = var_lookup_value_label (v, &f->value);
978       if (label != NULL)
979         tab_text (t, 0, r, TAB_LEFT, label);
980
981       tab_value (t, 1, r, TAB_NONE, &f->value, ft->dict, &vf->print);
982       tab_double (t, 2, r, TAB_NONE, f->count, wfmt);
983       tab_double (t, 3, r, TAB_NONE,
984                      f->count / ft->total_cases * 100.0, NULL);
985       tab_text (t, 4, r, TAB_NONE, _("Missing"));
986       r++;
987     }
988
989   tab_box (t, TAL_1, TAL_1, -1, TAL_1, 0, 0, 5, r);
990   tab_hline (t, TAL_2, 0, 5, 1);
991   tab_hline (t, TAL_2, 0, 5, r);
992   tab_joint_text (t, 0, r, 1, r, TAB_RIGHT | TAT_TITLE, _("Total"));
993   tab_vline (t, TAL_0, 1, r, r);
994   tab_double (t, 2, r, TAB_NONE, cum_freq, wfmt);
995   tab_fixed (t, 3, r, TAB_NONE, 100.0, 5, 1);
996   tab_fixed (t, 4, r, TAB_NONE, 100.0, 5, 1);
997
998   tab_title (t, "%s", var_to_string (v));
999   tab_submit (t);
1000 }
1001 \f
1002 /* Statistical display. */
1003
1004 /* Calculates all the pertinent statistics for variable V, putting them in
1005    array D[]. */
1006 static void
1007 calc_stats (const struct variable *v, double d[frq_n_stats])
1008 {
1009   struct freq_tab *ft = &get_var_freqs (v)->tab;
1010   double W = ft->valid_cases;
1011   struct moments *m;
1012   struct freq_mutable *f=0;
1013   int most_often;
1014   double X_mode;
1015
1016   double rank;
1017   int i = 0;
1018   int idx;
1019
1020   /* Calculate percentiles. */
1021
1022   assert (ft->n_valid > 0);
1023
1024   for (i = 0; i < n_percentiles; i++)
1025     {
1026       percentiles[i].flag = 0;
1027       percentiles[i].flag2 = 0;
1028     }
1029
1030   rank = 0;
1031   for (idx = 0; idx < ft->n_valid; ++idx)
1032     {
1033       static double prev_value = SYSMIS;
1034       f = &ft->valid[idx];
1035       rank += f->count ;
1036       for (i = 0; i < n_percentiles; i++)
1037         {
1038           double tp;
1039           if ( percentiles[i].flag2  ) continue ;
1040
1041           if ( settings_get_algorithm () != COMPATIBLE )
1042             tp =
1043               (ft->valid_cases - 1) *  percentiles[i].p;
1044           else
1045             tp =
1046               (ft->valid_cases + 1) *  percentiles[i].p - 1;
1047
1048           if ( percentiles[i].flag )
1049             {
1050               percentiles[i].x2 = f->value.f;
1051               percentiles[i].x1 = prev_value;
1052               percentiles[i].flag2 = 1;
1053               continue;
1054             }
1055
1056           if (rank >  tp )
1057           {
1058             if ( f->count > 1 && rank - (f->count - 1) > tp )
1059               {
1060                 percentiles[i].x2 = percentiles[i].x1 = f->value.f;
1061                 percentiles[i].flag2 = 1;
1062               }
1063             else
1064               {
1065                 percentiles[i].flag=1;
1066               }
1067
1068             continue;
1069           }
1070         }
1071       prev_value = f->value.f;
1072     }
1073
1074   for (i = 0; i < n_percentiles; i++)
1075     {
1076       /* Catches the case when p == 100% */
1077       if ( ! percentiles[i].flag2 )
1078         percentiles[i].x1 = percentiles[i].x2 = f->value.f;
1079
1080       /*
1081       printf("percentile %d (p==%.2f); X1 = %g; X2 = %g\n",
1082              i,percentiles[i].p,percentiles[i].x1,percentiles[i].x2);
1083       */
1084     }
1085
1086   for (i = 0; i < n_percentiles; i++)
1087     {
1088       struct freq_tab *ft = &get_var_freqs (v)->tab;
1089       double s;
1090
1091       double dummy;
1092       if ( settings_get_algorithm () != COMPATIBLE )
1093         {
1094           s = modf((ft->valid_cases - 1) * percentiles[i].p , &dummy);
1095         }
1096       else
1097         {
1098           s = modf((ft->valid_cases + 1) * percentiles[i].p -1, &dummy);
1099         }
1100
1101       percentiles[i].value = percentiles[i].x1 +
1102         ( percentiles[i].x2 - percentiles[i].x1) * s ;
1103     }
1104
1105
1106   /* Calculate the mode. */
1107   most_often = -1;
1108   X_mode = SYSMIS;
1109   for (f = ft->valid; f < ft->missing; f++)
1110     {
1111       if (most_often < f->count)
1112         {
1113           most_often = f->count;
1114           X_mode = f->value.f;
1115         }
1116       else if (most_often == f->count)
1117         {
1118           /* A duplicate mode is undefined.
1119              FIXME: keep track of *all* the modes. */
1120           X_mode = SYSMIS;
1121         }
1122     }
1123
1124   /* Calculate moments. */
1125   m = moments_create (MOMENT_KURTOSIS);
1126   for (f = ft->valid; f < ft->missing; f++)
1127     moments_pass_one (m, f->value.f, f->count);
1128   for (f = ft->valid; f < ft->missing; f++)
1129     moments_pass_two (m, f->value.f, f->count);
1130   moments_calculate (m, NULL, &d[frq_mean], &d[frq_variance],
1131                      &d[frq_skew], &d[frq_kurt]);
1132   moments_destroy (m);
1133
1134   /* Formulas below are taken from _SPSS Statistical Algorithms_. */
1135   d[frq_min] = ft->valid[0].value.f;
1136   d[frq_max] = ft->valid[ft->n_valid - 1].value.f;
1137   d[frq_mode] = X_mode;
1138   d[frq_range] = d[frq_max] - d[frq_min];
1139   d[frq_sum] = d[frq_mean] * W;
1140   d[frq_stddev] = sqrt (d[frq_variance]);
1141   d[frq_semean] = d[frq_stddev] / sqrt (W);
1142   d[frq_seskew] = calc_seskew (W);
1143   d[frq_sekurt] = calc_sekurt (W);
1144 }
1145
1146 /* Displays a table of all the statistics requested for variable V. */
1147 static void
1148 dump_statistics (const struct variable *v, const struct variable *wv)
1149 {
1150   const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : &F_8_0;
1151   struct freq_tab *ft;
1152   double stat_value[frq_n_stats];
1153   struct tab_table *t;
1154   int i, r;
1155
1156   if (var_is_alpha (v))
1157     return;
1158   ft = &get_var_freqs (v)->tab;
1159   if (ft->n_valid == 0)
1160     {
1161       msg (SW, _("No valid data for variable %s; statistics not displayed."),
1162            var_get_name (v));
1163       return;
1164     }
1165   calc_stats (v, stat_value);
1166
1167   t = tab_create (3, n_stats + n_show_percentiles + 2);
1168
1169   tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ;
1170
1171
1172   tab_vline (t, TAL_1 , 2, 0, tab_nr(t) - 1);
1173   tab_vline (t, TAL_GAP , 1, 0, tab_nr(t) - 1 ) ;
1174
1175   r=2; /* N missing and N valid are always dumped */
1176
1177   for (i = 0; i < frq_n_stats; i++)
1178     if (stats & BIT_INDEX (i))
1179       {
1180         tab_text (t, 0, r, TAB_LEFT | TAT_TITLE,
1181                       gettext (st_name[i].s10));
1182         tab_double (t, 2, r, TAB_NONE, stat_value[i], NULL);
1183         r++;
1184       }
1185
1186   tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("N"));
1187   tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Valid"));
1188   tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("Missing"));
1189
1190   tab_double (t, 2, 0, TAB_NONE, ft->valid_cases, wfmt);
1191   tab_double (t, 2, 1, TAB_NONE, ft->total_cases - ft->valid_cases, wfmt);
1192
1193   for (i = 0; i < n_percentiles; i++, r++)
1194     {
1195       if (!percentiles[i].show)
1196         continue;
1197
1198       if ( i == 0 )
1199         {
1200           tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Percentiles"));
1201         }
1202
1203       if (percentiles[i].p == 0.5)
1204         tab_text (t, 1, r, TAB_LEFT, _("50 (Median)"));
1205       else
1206         tab_fixed (t, 1, r, TAB_LEFT, percentiles[i].p * 100, 3, 0);
1207       tab_double (t, 2, r, TAB_NONE, percentiles[i].value,
1208                   var_get_print_format (v));
1209     }
1210
1211   tab_title (t, "%s", var_to_string (v));
1212
1213   tab_submit (t);
1214 }
1215
1216 static double
1217 calculate_iqr (void)
1218 {
1219   double q1 = SYSMIS;
1220   double q3 = SYSMIS;
1221   int i;
1222
1223   for (i = 0; i < n_percentiles; i++)
1224     {
1225       if (fabs (0.25 - percentiles[i].p) < DBL_EPSILON)
1226         q1 = percentiles[i].value;
1227       else if (fabs (0.75 - percentiles[i].p) < DBL_EPSILON)
1228         q3 = percentiles[i].value;
1229     }
1230
1231   return q1 == SYSMIS || q3 == SYSMIS ? SYSMIS : q3 - q1;
1232 }
1233
1234 static bool
1235 chart_includes_value (const struct frq_chart *chart,
1236                       const struct variable *var,
1237                       const union value *value)
1238 {
1239   if (!chart->include_missing && var_is_value_missing (var, value, MV_ANY))
1240     return false;
1241
1242   if (var_is_numeric (var)
1243       && ((chart->x_min != SYSMIS && value->f < chart->x_min)
1244           || (chart->x_max != SYSMIS && value->f > chart->x_max)))
1245     return false;
1246
1247   return true;
1248 }
1249
1250 /* Create a gsl_histogram from a freq_tab */
1251 struct histogram *
1252 freq_tab_to_hist (const struct freq_tab *ft, const struct variable *var)
1253 {
1254   double x_min, x_max, valid_freq;
1255   int i;
1256
1257   struct histogram *histogram;
1258   double iqr;
1259   int bins;
1260
1261   /* Find out the extremes of the x value, within the range to be included in
1262      the histogram, and sum the total frequency of those values. */
1263   x_min = DBL_MAX;
1264   x_max = -DBL_MAX;
1265   valid_freq = 0;
1266   for (i = 0; i < ft->n_valid; i++)
1267     {
1268       const struct freq_mutable *frq = &ft->valid[i];
1269       if (chart_includes_value (&hist, var, &frq->value))
1270         {
1271           x_min = MIN (x_min, frq->value.f);
1272           x_max = MAX (x_max, frq->value.f);
1273           valid_freq += frq->count;
1274         }
1275     }
1276
1277   /* Freedman-Diaconis' choice of bin width. */
1278   iqr = calculate_iqr ();
1279   if (iqr != SYSMIS)
1280     {
1281       double bin_width = 2 * iqr / pow (valid_freq, 1.0 / 3.0);
1282       bins = (x_max - x_min) / bin_width;
1283       if (bins < 5)
1284         bins = 5;
1285       else if (bins > 400)
1286         bins = 400;
1287     }
1288   else
1289     bins = 5;
1290
1291   histogram = histogram_create (bins, x_min, x_max);
1292   for (i = 0; i < ft->n_valid; i++)
1293     {
1294       const struct freq_mutable *frq = &ft->valid[i];
1295       if (chart_includes_value (&hist, var, &frq->value))
1296         histogram_add (histogram, frq->value.f, frq->count);
1297     }
1298
1299   return histogram;
1300 }
1301
1302 static int
1303 add_slice (const struct freq_mutable *freq, const struct variable *var,
1304            struct slice *slice)
1305 {
1306   if (chart_includes_value (&pie, var, &freq->value))
1307     {
1308       ds_init_empty (&slice->label);
1309       var_append_value_name (var, &freq->value, &slice->label);
1310       slice->magnitude = freq->count;
1311       return 1;
1312     }
1313   else
1314     return 0;
1315 }
1316
1317 /* Allocate an array of slices and fill them from the data in frq_tab
1318    n_slices will contain the number of slices allocated.
1319    The caller is responsible for freeing slices
1320 */
1321 static struct slice *
1322 freq_tab_to_slice_array(const struct freq_tab *frq_tab,
1323                         const struct variable *var,
1324                         int *n_slicesp)
1325 {
1326   struct slice *slices;
1327   int n_slices;
1328   int i;
1329
1330   slices = xnmalloc (frq_tab->n_valid + frq_tab->n_missing, sizeof *slices);
1331   n_slices = 0;
1332
1333   for (i = 0; i < frq_tab->n_valid; i++)
1334     n_slices += add_slice (&frq_tab->valid[i], var, &slices[n_slices]);
1335   for (i = 0; i < frq_tab->n_missing; i++)
1336     n_slices += add_slice (&frq_tab->missing[i], var, &slices[n_slices]);
1337
1338   *n_slicesp = n_slices;
1339   return slices;
1340 }
1341
1342
1343
1344
1345 static void
1346 do_piechart(const struct variable *var, const struct freq_tab *frq_tab)
1347 {
1348   struct slice *slices;
1349   int n_slices, i;
1350
1351   slices = freq_tab_to_slice_array (frq_tab, var, &n_slices);
1352
1353   if (n_slices < 2)
1354     msg (SW, _("Omitting pie chart for %s, which has only %d unique values."),
1355          var_get_name (var), n_slices);
1356   else if (n_slices > 50)
1357     msg (SW, _("Omitting pie chart for %s, which has over 50 unique values."),
1358          var_get_name (var));
1359   else
1360     chart_item_submit (piechart_create (var_to_string(var), slices, n_slices));
1361
1362   for (i = 0; i < n_slices; i++)
1363     ds_destroy (&slices[i].label);
1364   free (slices);
1365 }
1366
1367
1368 /*
1369    Local Variables:
1370    mode: c
1371    End:
1372 */