X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Ffrequencies.c;h=3e4455f2b2d4ba910f5f75d45f0190f669b7052a;hb=6e097c89af440da90b43ce90864394c4d0c843d5;hp=7cd604c1f6e2ea20ace66080446a1d405be1d097;hpb=1e0e76eaeb51ef0c15fdcfc4bd12d9310c16a88b;p=pspp diff --git a/src/language/stats/frequencies.c b/src/language/stats/frequencies.c index 7cd604c1f6..3e4455f2b2 100644 --- a/src/language/stats/frequencies.c +++ b/src/language/stats/frequencies.c @@ -1,7 +1,7 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2014 Free Software Foundation, Inc. - + Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2014, 2015 Free Software Foundation, Inc. + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -53,6 +53,7 @@ #include "output/chart-item.h" +#include "output/charts/barchart.h" #include "output/charts/piechart.h" #include "output/charts/plot-hist.h" #include "output/tab.h" @@ -82,6 +83,14 @@ ptile_3way (const void *_p1, const void *_p2) if (p1->p < p2->p) return -1; + if (p1->p == p2->p) + { + if (p1->show > p2->show) + return -1; + + return (p1->show < p2->show); + } + return (p1->p > p2->p); } @@ -98,7 +107,7 @@ enum FRQ_PERCENT }; -enum sortprops +enum sortprops { FRQ_AFREQ, FRQ_DFREQ, @@ -205,7 +214,7 @@ struct frq_proc int n_percentiles, n_show_percentiles; /* Frequency table display. */ - int max_categories; /* Maximum categories to show. */ + long int max_categories; /* Maximum categories to show. */ int sort; /* FRQ_AVALUE or FRQ_DVALUE or FRQ_AFREQ or FRQ_DFREQ. */ @@ -214,7 +223,7 @@ struct frq_proc int n_stats; /* Histogram and pie chart settings. */ - struct frq_chart *hist, *pie; + struct frq_chart *hist, *pie, *bar; }; @@ -229,11 +238,15 @@ struct freq_compare_aux static void calc_stats (const struct var_freqs *vf, double d[FRQ_ST_count]); -static void do_piechart(const struct frq_chart *pie, +static void do_piechart(const struct frq_chart *pie, const struct variable *var, const struct freq_tab *frq_tab); -static void dump_statistics (const struct frq_proc *frq, +static void do_barchart(const struct frq_chart *bar, + const struct variable **var, + const struct freq_tab *frq_tab); + +static void dump_statistics (const struct frq_proc *frq, const struct var_freqs *vf, const struct variable *wv); @@ -251,7 +264,7 @@ compare_freq (const void *a_, const void *b_, const void *aux_) } else { - int cmp = value_compare_3way (&a->value, &b->value, aux->width); + int cmp = value_compare_3way (a->values, b->values, aux->width); return aux->ascending_value ? cmp : -cmp; } } @@ -304,11 +317,11 @@ dump_freq_table (const struct var_freqs *vf, const struct variable *wv) valid_percent = f->count / ft->valid_cases * 100.0; cum_total += valid_percent; - label = var_lookup_value_label (vf->var, &f->value); + label = var_lookup_value_label (vf->var, f->values); if (label != NULL) tab_text (t, 0, r, TAB_LEFT, label); - tab_value (t, 1, r, TAB_NONE, &f->value, vf->var, NULL); + tab_value (t, 1, r, TAB_NONE, f->values, vf->var, NULL); tab_double (t, 2, r, TAB_NONE, f->count, NULL, RC_WEIGHT); tab_double (t, 3, r, TAB_NONE, percent, NULL, RC_OTHER); tab_double (t, 4, r, TAB_NONE, valid_percent, NULL, RC_OTHER); @@ -321,11 +334,11 @@ dump_freq_table (const struct var_freqs *vf, const struct variable *wv) cum_freq += f->count; - label = var_lookup_value_label (vf->var, &f->value); + label = var_lookup_value_label (vf->var, f->values); if (label != NULL) tab_text (t, 0, r, TAB_LEFT, label); - tab_value (t, 1, r, TAB_NONE, &f->value, vf->var, NULL); + tab_value (t, 1, r, TAB_NONE, f->values, vf->var, NULL); tab_double (t, 2, r, TAB_NONE, f->count, NULL, RC_WEIGHT); tab_double (t, 3, r, TAB_NONE, f->count / ft->total_cases * 100.0, NULL, RC_OTHER); @@ -367,13 +380,9 @@ calc_percentiles (const struct frq_proc *frq, const struct var_freqs *vf) const struct freq_tab *ft = &vf->tab; double W = ft->valid_cases; const struct freq *f; - int percentile_idx; - double rank; + int percentile_idx = 0; + double rank = 0; - assert (ft->n_valid > 0); - - rank = 0; - percentile_idx = 0; for (f = ft->valid; f < ft->missing; f++) { rank += f->count; @@ -390,15 +399,15 @@ calc_percentiles (const struct frq_proc *frq, const struct var_freqs *vf) break; if (tp + 1 < rank || f + 1 >= ft->missing) - pc->value = f->value.f; + pc->value = f->values[0].f; else - pc->value = calc_percentile (pc->p, W, f->value.f, f[1].value.f); + pc->value = calc_percentile (pc->p, W, f->values[0].f, f[1].values[0].f); } } for (; percentile_idx < frq->n_percentiles; percentile_idx++) { struct percentile *pc = &frq->percentiles[percentile_idx]; - pc->value = ft->valid[ft->n_valid - 1].value.f; + pc->value = ft->valid[ft->n_valid - 1].values[0].f; } } @@ -410,7 +419,7 @@ not_missing (const void *f_, const void *v_) const struct freq *f = f_; const struct variable *v = v_; - return !var_is_value_missing (v, &f->value, MV_ANY); + return !var_is_value_missing (v, f->values, MV_ANY); } @@ -559,6 +568,9 @@ postcalc (struct frq_proc *frq, const struct dataset *ds) if (frq->pie) do_piechart(frq->pie, vf->var, &vf->tab); + if (frq->bar) + do_barchart(frq->bar, &vf->var, &vf->tab); + cleanup_freq_tab (vf); } } @@ -568,7 +580,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { int i; struct frq_proc frq; - const struct variable **vars; + const struct variable **vars = NULL; bool sbc_barchart = false; bool sbc_piechart = false; @@ -576,7 +588,11 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) double pie_min = -DBL_MAX; double pie_max = DBL_MAX; - bool pie_missing = false; + bool pie_missing = true; + + double bar_min = -DBL_MAX; + double bar_max = DBL_MAX; + bool bar_freq = true; double hi_min = -DBL_MAX; double hi_max = DBL_MAX; @@ -590,15 +606,15 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) frq.vars = NULL; frq.n_vars = 0; - - frq.stats = BIT_INDEX (FRQ_ST_MEAN) - | BIT_INDEX (FRQ_ST_STDDEV) + + frq.stats = BIT_INDEX (FRQ_ST_MEAN) + | BIT_INDEX (FRQ_ST_STDDEV) | BIT_INDEX (FRQ_ST_MINIMUM) | BIT_INDEX (FRQ_ST_MAXIMUM); frq.n_stats = 4; - frq.max_categories = INT_MAX; + frq.max_categories = LONG_MAX; frq.percentiles = NULL; frq.n_percentiles = 0; @@ -606,6 +622,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) frq.hist = NULL; frq.pie = NULL; + frq.bar = NULL; /* Accept an optional, completely pointless "/VARIABLES=" */ @@ -626,6 +643,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) for (i = 0; i < frq.n_vars; ++i) { frq.vars[i].var = vars[i]; + frq.vars[i].width = var_get_width (vars[i]); } while (lex_token (lexer) != T_ENDCMD) @@ -634,18 +652,26 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) if (lex_match_id (lexer, "STATISTICS")) { - lex_match (lexer, T_EQUALS); + frq.stats = BIT_INDEX (FRQ_ST_MEAN) + | BIT_INDEX (FRQ_ST_STDDEV) + | BIT_INDEX (FRQ_ST_MINIMUM) + | BIT_INDEX (FRQ_ST_MAXIMUM); - frq.stats = 0; - frq.n_stats = 0; + frq.n_stats = 4; + + if (lex_match (lexer, T_EQUALS)) + { + frq.n_stats = 0; + frq.stats = 0; + } while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH) { if (lex_match_id (lexer, "DEFAULT")) { - frq.stats = BIT_INDEX (FRQ_ST_MEAN) - | BIT_INDEX (FRQ_ST_STDDEV) + frq.stats = BIT_INDEX (FRQ_ST_MEAN) + | BIT_INDEX (FRQ_ST_STDDEV) | BIT_INDEX (FRQ_ST_MINIMUM) | BIT_INDEX (FRQ_ST_MAXIMUM); @@ -678,7 +704,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) } else if (lex_match_id (lexer, "VARIANCE")) { - frq.stats |= BIT_INDEX (FRQ_ST_MEAN); + frq.stats |= BIT_INDEX (FRQ_ST_VARIANCE); frq.n_stats++; } else if (lex_match_id (lexer, "KURTOSIS")) @@ -747,7 +773,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) if (lex_force_num (lexer)) { frq.percentiles = - xrealloc (frq.percentiles, + xrealloc (frq.percentiles, (frq.n_percentiles + 1) * sizeof (*frq.percentiles)); frq.percentiles[frq.n_percentiles].p = lex_number (lexer) / 100.0; @@ -761,6 +787,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) lex_error (lexer, NULL); goto error; } + lex_match (lexer, T_COMMA); } } else if (lex_match_id (lexer, "FORMAT")) @@ -771,12 +798,23 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { if (lex_match_id (lexer, "TABLE")) { - } else if (lex_match_id (lexer, "NOTABLE")) { frq.max_categories = 0; } + else if (lex_match_id (lexer, "LIMIT")) + { + if (!lex_force_match (lexer, T_LPAREN) + || !lex_force_int (lexer)) + goto error; + + frq.max_categories = lex_integer (lexer); + lex_get (lexer); + + if (!lex_force_match (lexer, T_RPAREN)) + goto error; + } else if (lex_match_id (lexer, "AVALUE")) { frq.sort = FRQ_AVALUE; @@ -812,7 +850,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) for (i = 0; i < n + 1; ++i) { frq.percentiles = - xrealloc (frq.percentiles, + xrealloc (frq.percentiles, (frq.n_percentiles + 1) * sizeof (*frq.percentiles)); frq.percentiles[frq.n_percentiles].p = @@ -876,7 +914,8 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) lex_error (lexer, _("Histogram frequency must be greater than zero.")); } lex_get (lexer); - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } } } @@ -890,32 +929,37 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) hi_pcnt = lex_integer (lexer); if (hi_pcnt <= 0) { - lex_error (lexer, _("Histogram percentaage must be greater than zero.")); + lex_error (lexer, _("Histogram percentage must be greater than zero.")); } lex_get (lexer); - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } } } else if (lex_match_id (lexer, "MINIMUM")) { - lex_force_match (lexer, T_LPAREN); + if (! lex_force_match (lexer, T_LPAREN)) + goto error; if (lex_force_num (lexer)) { hi_min = lex_number (lexer); lex_get (lexer); } - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } else if (lex_match_id (lexer, "MAXIMUM")) { - lex_force_match (lexer, T_LPAREN); + if (! lex_force_match (lexer, T_LPAREN)) + goto error; if (lex_force_num (lexer)) { hi_max = lex_number (lexer); lex_get (lexer); } - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } else { @@ -932,23 +976,27 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { if (lex_match_id (lexer, "MINIMUM")) { - lex_force_match (lexer, T_LPAREN); + if (! lex_force_match (lexer, T_LPAREN)) + goto error; if (lex_force_num (lexer)) { pie_min = lex_number (lexer); lex_get (lexer); } - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } else if (lex_match_id (lexer, "MAXIMUM")) { - lex_force_match (lexer, T_LPAREN); + if (! lex_force_match (lexer, T_LPAREN)) + goto error; if (lex_force_num (lexer)) { pie_max = lex_number (lexer); lex_get (lexer); } - lex_force_match (lexer, T_RPAREN); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; } else if (lex_match_id (lexer, "MISSING")) { @@ -966,6 +1014,72 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) } sbc_piechart = true; } + else if (lex_match_id (lexer, "BARCHART")) + { + lex_match (lexer, T_EQUALS); + while (lex_token (lexer) != T_ENDCMD + && lex_token (lexer) != T_SLASH) + { + if (lex_match_id (lexer, "MINIMUM")) + { + if (! lex_force_match (lexer, T_LPAREN)) + goto error; + if (lex_force_num (lexer)) + { + bar_min = lex_number (lexer); + lex_get (lexer); + } + if (! lex_force_match (lexer, T_RPAREN)) + goto error; + } + else if (lex_match_id (lexer, "MAXIMUM")) + { + if (! lex_force_match (lexer, T_LPAREN)) + goto error; + if (lex_force_num (lexer)) + { + bar_max = lex_number (lexer); + lex_get (lexer); + } + if (! lex_force_match (lexer, T_RPAREN)) + goto error; + } + else if (lex_match_id (lexer, "FREQ")) + { + if ( lex_match (lexer, T_LPAREN)) + { + if (lex_force_num (lexer)) + { + lex_number (lexer); + lex_get (lexer); + } + if (! lex_force_match (lexer, T_RPAREN)) + goto error; + } + bar_freq = true; + } + else if (lex_match_id (lexer, "PERCENT")) + { + if ( lex_match (lexer, T_LPAREN)) + { + if (lex_force_num (lexer)) + { + lex_number (lexer); + lex_get (lexer); + } + if (! lex_force_match (lexer, T_RPAREN)) + goto error; + } + bar_freq = false; + } + else + { + lex_error (lexer, NULL); + goto error; + } + } + sbc_barchart = true; + } else if (lex_match_id (lexer, "MISSING")) { lex_match (lexer, T_EQUALS); @@ -986,6 +1100,12 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) } } } + else if (lex_match_id (lexer, "ORDER")) + { + lex_match (lexer, T_EQUALS); + if (!lex_match_id (lexer, "ANALYSIS")) + lex_match_id (lexer, "VARIABLE"); + } else { lex_error (lexer, NULL); @@ -993,26 +1113,24 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) } } - if (frq.stats & FRQ_ST_MEDIAN) + if (frq.stats & BIT_INDEX (FRQ_ST_MEDIAN)) { frq.percentiles = - xrealloc (frq.percentiles, + xrealloc (frq.percentiles, (frq.n_percentiles + 1) * sizeof (*frq.percentiles)); - + frq.percentiles[frq.n_percentiles].p = 0.50; frq.percentiles[frq.n_percentiles].show = true; frq.n_percentiles++; + frq.n_show_percentiles++; } /* Figure out which charts the user requested. */ { - if (sbc_barchart) - msg (SW, _("Bar charts are not implemented.")); - if (sbc_histogram) { struct frq_chart *hist; @@ -1031,27 +1149,36 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) msg (SE, _("%s for histogram must be greater than or equal to %s, " "but %s was specified as %.15g and %s as %.15g. " "%s and %s will be ignored."), - "MAX", "MIN", - "MIN", hist->x_min, + "MAX", "MIN", + "MIN", hist->x_min, "MAX", hist->x_max, "MIN", "MAX"); hist->x_min = hist->x_max = SYSMIS; } frq.percentiles = - xrealloc (frq.percentiles, + xrealloc (frq.percentiles, (frq.n_percentiles + 2) * sizeof (*frq.percentiles)); - + frq.percentiles[frq.n_percentiles].p = 0.25; frq.percentiles[frq.n_percentiles].show = false; frq.percentiles[frq.n_percentiles + 1].p = 0.75; frq.percentiles[frq.n_percentiles + 1].show = false; - + frq.n_percentiles+=2; } + if (sbc_barchart) + { + frq.bar = xmalloc (sizeof *frq.bar); + frq.bar->x_min = bar_min; + frq.bar->x_max = bar_max; + frq.bar->include_missing = false; + frq.bar->y_scale = bar_freq ? FRQ_FREQ : FRQ_PERCENT; + } + if (sbc_piechart) { struct frq_chart *pie; @@ -1066,8 +1193,8 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { msg (SE, _("%s for pie chart must be greater than or equal to %s, " "but %s was specified as %.15g and %s as %.15g. " - "%s and %s will be ignored."), - "MAX", "MIN", + "%s and %s will be ignored."), + "MAX", "MIN", "MIN", pie->x_min, "MAX", pie->x_max, "MIN", "MAX"); @@ -1080,25 +1207,26 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) int i,o; double previous_p = -1; qsort (frq.percentiles, frq.n_percentiles, - sizeof (*frq.percentiles), + sizeof (*frq.percentiles), ptile_3way); frq.n_show_percentiles = 0; for (i = o = 0; i < frq.n_percentiles; ++i) { - frq.percentiles[o].p = frq.percentiles[i].p; - - if (frq.percentiles[i].show) - frq.percentiles[o].show = true; - - if (frq.percentiles[i].p != previous_p) - { - if (frq.percentiles[i].show) - frq.n_show_percentiles++; - - o++; - } - + if (frq.percentiles[i].p != previous_p) + { + frq.percentiles[o].p = frq.percentiles[i].p; + frq.percentiles[o].show = frq.percentiles[i].show; + if (frq.percentiles[i].show) + frq.n_show_percentiles++; + o++; + } + else if (frq.percentiles[i].show && + !frq.percentiles[o].show) + { + frq.percentiles[o].show = true; + frq.n_show_percentiles++; + } previous_p = frq.percentiles[i].p; } @@ -1115,19 +1243,37 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { struct ccase *c; precalc (&frq, group, ds); + for (; (c = casereader_read (group)) != NULL; case_unref (c)) calc (&frq, c, ds); postcalc (&frq, ds); + casereader_destroy (group); } ok = casegrouper_destroy (grouper); ok = proc_commit (ds) && ok; } + free (vars); + free (frq.vars); + free (frq.bar); + free (frq.pie); + free (frq.hist); + free (frq.percentiles); + pool_destroy (frq.pool); + return CMD_SUCCESS; error: + free (vars); + free (frq.vars); + free (frq.bar); + free (frq.pie); + free (frq.hist); + free (frq.percentiles); + pool_destroy (frq.pool); + return CMD_FAILURE; } @@ -1188,14 +1334,16 @@ freq_tab_to_hist (const struct frq_proc *frq, const struct freq_tab *ft, for (i = 0; i < ft->n_valid; i++) { const struct freq *f = &ft->valid[i]; - if (chart_includes_value (frq->hist, var, &f->value)) + if (chart_includes_value (frq->hist, var, f->values)) { - x_min = MIN (x_min, f->value.f); - x_max = MAX (x_max, f->value.f); + x_min = MIN (x_min, f->values[0].f); + x_max = MAX (x_max, f->values[0].f); valid_freq += f->count; } } + if (valid_freq <= 0) + return NULL; iqr = calculate_iqr (frq); @@ -1215,63 +1363,118 @@ freq_tab_to_hist (const struct frq_proc *frq, const struct freq_tab *ft, for (i = 0; i < ft->n_valid; i++) { const struct freq *f = &ft->valid[i]; - if (chart_includes_value (frq->hist, var, &f->value)) - histogram_add (histogram, f->value.f, f->count); + if (chart_includes_value (frq->hist, var, f->values)) + histogram_add (histogram, f->values[0].f, f->count); } return histogram; } -static int -add_slice (const struct frq_chart *pie, const struct freq *freq, - const struct variable *var, struct slice *slice) + +/* Allocate an array of struct freqs and fill them from the data in FRQ_TAB, + according to the parameters of CATCHART + N_SLICES will contain the number of slices allocated. + The caller is responsible for freeing slices +*/ +static struct freq * +pick_cat_counts (const struct frq_chart *catchart, + const struct freq_tab *frq_tab, + int *n_slicesp) { - if (chart_includes_value (pie, var, &freq->value)) + int n_slices = 0; + int i; + struct freq *slices = xnmalloc (frq_tab->n_valid + frq_tab->n_missing, sizeof *slices); + + for (i = 0; i < frq_tab->n_valid; i++) + { + const struct freq *f = &frq_tab->valid[i]; + if (f->count > catchart->x_max) + continue; + + if (f->count < catchart->x_min) + continue; + + slices[n_slices] = *f; + + n_slices++; + } + + if (catchart->include_missing) { - ds_init_empty (&slice->label); - var_append_value_name (var, &freq->value, &slice->label); - slice->magnitude = freq->count; - return 1; + for (i = 0; i < frq_tab->n_missing; i++) + { + const struct freq *f = &frq_tab->missing[i]; + slices[n_slices].count += f->count; + + if (i == 0) + slices[n_slices].values[0] = f->values[0]; + } + + if (frq_tab->n_missing > 0) + n_slices++; } - else - return 0; + + *n_slicesp = n_slices; + return slices; } -/* Allocate an array of slices and fill them from the data in frq_tab - n_slices will contain the number of slices allocated. + +/* Allocate an array of struct freqs and fill them from the data in FRQ_TAB, + according to the parameters of CATCHART + N_SLICES will contain the number of slices allocated. The caller is responsible for freeing slices */ -static struct slice * -freq_tab_to_slice_array(const struct frq_chart *pie, - const struct freq_tab *frq_tab, - const struct variable *var, - int *n_slicesp) +static struct freq ** +pick_cat_counts_ptr (const struct frq_chart *catchart, + const struct freq_tab *frq_tab, + int *n_slicesp) { - struct slice *slices; - int n_slices; + int n_slices = 0; int i; - - slices = xnmalloc (frq_tab->n_valid + frq_tab->n_missing, sizeof *slices); - n_slices = 0; + struct freq **slices = xnmalloc (frq_tab->n_valid + frq_tab->n_missing, sizeof *slices); for (i = 0; i < frq_tab->n_valid; i++) - n_slices += add_slice (pie, &frq_tab->valid[i], var, &slices[n_slices]); - for (i = 0; i < frq_tab->n_missing; i++) - n_slices += add_slice (pie, &frq_tab->missing[i], var, &slices[n_slices]); + { + struct freq *f = &frq_tab->valid[i]; + if (f->count > catchart->x_max) + continue; + + if (f->count < catchart->x_min) + continue; + + slices[n_slices] = f; + + n_slices++; + } + + if (catchart->include_missing) + { + for (i = 0; i < frq_tab->n_missing; i++) + { + const struct freq *f = &frq_tab->missing[i]; + if (i == 0) + { + slices[n_slices] = xmalloc (sizeof (struct freq)); + slices[n_slices]->values[0] = f->values[0]; + } + + slices[n_slices]->count += f->count; + + } + } *n_slicesp = n_slices; return slices; } + static void do_piechart(const struct frq_chart *pie, const struct variable *var, const struct freq_tab *frq_tab) { - struct slice *slices; - int n_slices, i; - - slices = freq_tab_to_slice_array (pie, frq_tab, var, &n_slices); + int n_slices; + struct freq *slices = pick_cat_counts (pie, frq_tab, &n_slices); if (n_slices < 2) msg (SW, _("Omitting pie chart for %s, which has only %d unique values."), @@ -1280,13 +1483,27 @@ do_piechart(const struct frq_chart *pie, const struct variable *var, msg (SW, _("Omitting pie chart for %s, which has over 50 unique values."), var_get_name (var)); else - chart_item_submit (piechart_create (var_to_string(var), slices, n_slices)); + chart_item_submit (piechart_create (var, slices, n_slices)); + + free (slices); +} - for (i = 0; i < n_slices; i++) - ds_destroy (&slices[i].label); + +static void +do_barchart(const struct frq_chart *bar, const struct variable **var, + const struct freq_tab *frq_tab) +{ + int n_slices; + struct freq **slices = pick_cat_counts_ptr (bar, frq_tab, &n_slices); + + chart_item_submit (barchart_create (var, 1, + (bar->y_scale == FRQ_FREQ) ? _("Count") : _("Percent"), + (bar->y_scale == FRQ_PERCENT), + slices, n_slices)); free (slices); } + /* Calculates all the pertinent statistics for VF, putting them in array D[]. */ static void @@ -1296,20 +1513,16 @@ calc_stats (const struct var_freqs *vf, double d[FRQ_ST_count]) double W = ft->valid_cases; const struct freq *f; struct moments *m; - int most_often; - double X_mode; - - assert (ft->n_valid > 0); + int most_often = -1; + double X_mode = SYSMIS; /* Calculate the mode. */ - most_often = -1; - X_mode = SYSMIS; for (f = ft->valid; f < ft->missing; f++) { if (most_often < f->count) { most_often = f->count; - X_mode = f->value.f; + X_mode = f->values[0].f; } else if (most_often == f->count) { @@ -1322,16 +1535,16 @@ calc_stats (const struct var_freqs *vf, double d[FRQ_ST_count]) /* Calculate moments. */ m = moments_create (MOMENT_KURTOSIS); for (f = ft->valid; f < ft->missing; f++) - moments_pass_one (m, f->value.f, f->count); + moments_pass_one (m, f->values[0].f, f->count); for (f = ft->valid; f < ft->missing; f++) - moments_pass_two (m, f->value.f, f->count); + moments_pass_two (m, f->values[0].f, f->count); moments_calculate (m, NULL, &d[FRQ_ST_MEAN], &d[FRQ_ST_VARIANCE], &d[FRQ_ST_SKEWNESS], &d[FRQ_ST_KURTOSIS]); moments_destroy (m); - /* Formulas below are taken from _SPSS Statistical Algorithms_. */ - d[FRQ_ST_MINIMUM] = ft->valid[0].value.f; - d[FRQ_ST_MAXIMUM] = ft->valid[ft->n_valid - 1].value.f; + /* Formulae below are taken from _SPSS Statistical Algorithms_. */ + d[FRQ_ST_MINIMUM] = ft->valid[0].values[0].f; + d[FRQ_ST_MAXIMUM] = ft->valid[ft->n_valid - 1].values[0].f; d[FRQ_ST_MODE] = X_mode; d[FRQ_ST_RANGE] = d[FRQ_ST_MAXIMUM] - d[FRQ_ST_MINIMUM]; d[FRQ_ST_SUM] = d[FRQ_ST_MEAN] * W; @@ -1350,30 +1563,22 @@ dump_statistics (const struct frq_proc *frq, const struct var_freqs *vf, const struct freq_tab *ft = &vf->tab; double stat_value[FRQ_ST_count]; struct tab_table *t; - int i, r; + int i, r = 2; /* N missing and N valid are always dumped */ if (var_is_alpha (vf->var)) return; - if (ft->n_valid == 0) - { - msg (SW, _("No valid data for variable %s; statistics not displayed."), - var_get_name (vf->var)); - return; - } calc_stats (vf, stat_value); - t = tab_create (3, ((frq->stats & FRQ_ST_MEDIAN) ? frq->n_stats - 1 : frq->n_stats) - + frq->n_show_percentiles + 2); + t = tab_create (3, ((frq->stats & BIT_INDEX (FRQ_ST_MEDIAN)) ? frq->n_stats - 1 : frq->n_stats) + + frq->n_show_percentiles + 2); + tab_set_format (t, RC_WEIGHT, wfmt); tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ; - tab_vline (t, TAL_1 , 2, 0, tab_nr(t) - 1); tab_vline (t, TAL_GAP , 1, 0, tab_nr(t) - 1 ) ; - r = 2; /* N missing and N valid are always dumped */ - for (i = 0; i < FRQ_ST_count; i++) { if (FRQ_ST_MEDIAN == i) @@ -1383,7 +1588,11 @@ dump_statistics (const struct frq_proc *frq, const struct var_freqs *vf, { tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, gettext (st_name[i])); - tab_double (t, 2, r, TAB_NONE, stat_value[i], NULL, RC_OTHER); + + if (vf->tab.n_valid <= 0 && r >= 2) + tab_text (t, 2, r, 0, "."); + else + tab_double (t, 2, r, TAB_NONE, stat_value[i], NULL, RC_OTHER); r++; } } @@ -1407,13 +1616,21 @@ dump_statistics (const struct frq_proc *frq, const struct var_freqs *vf, tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Percentiles")); } + if (vf->tab.n_valid <= 0) + { + tab_text (t, 2, r, 0, "."); + ++r; + continue; + } + if (pc->p == 0.5) tab_text (t, 1, r, TAB_LEFT, _("50 (Median)")); else tab_double (t, 1, r, TAB_LEFT, pc->p * 100, NULL, RC_INTEGER); tab_double (t, 2, r, TAB_NONE, pc->value, var_get_print_format (vf->var), RC_OTHER); - r++; + + ++r; } tab_title (t, "%s", var_to_string (vf->var));