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