X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Ffrequencies.q;h=25866a417acd109d1c715dec892bdef27294f2f5;hb=9e0e4996fad6563f0a1ce628b80db5c23ef8279e;hp=0934fc4afadc85e69c29bc93fbf2354591ccbdea;hpb=3511d7ae23264f6f06d9315389607570814c8b21;p=pspp-builds.git diff --git a/src/language/stats/frequencies.q b/src/language/stats/frequencies.q index 0934fc4a..25866a41 100644 --- a/src/language/stats/frequencies.q +++ b/src/language/stats/frequencies.q @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009 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 @@ -38,12 +38,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -60,6 +58,7 @@ #include "freq.h" #include "minmax.h" +#include "xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -156,8 +155,6 @@ static void add_percentile (double x) ; static struct percentile *percentiles; static int n_percentiles; -static int implicit_50th ; - /* Groups of statistics. */ #define BI BIT_INDEX #define frq_default \ @@ -254,12 +251,12 @@ static void calc_stats (const struct variable *v, double d[frq_n_stats]); static void precalc (struct casereader *, struct dataset *); static void calc (const struct ccase *, const struct dataset *); -static void postcalc (void); +static void postcalc (const struct dataset *); static void postprocess_freq_tab (const struct variable *); -static void dump_full (const struct variable *); -static void dump_condensed (const struct variable *); -static void dump_statistics (const struct variable *, int show_varname); +static void dump_full ( const struct variable *, const struct variable *); +static void dump_condensed (const struct variable *, const struct variable *); +static void dump_statistics (const struct variable *, bool show_varname, const struct variable *); static void cleanup_freq_tab (const struct variable *); static hsh_compare_func compare_value_numeric_a, compare_value_alpha_a; @@ -271,7 +268,7 @@ static hsh_compare_func compare_freq_numeric_d, compare_freq_alpha_d; static void do_piechart(const struct variable *var, const struct freq_tab *frq_tab); -gsl_histogram * +struct histogram * freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var); @@ -313,7 +310,7 @@ internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds) if (!parse_frequencies (lexer, ds, &cmd, NULL)) return CMD_FAILURE; - if (cmd.onepage_limit == NOT_LONG) + if (cmd.onepage_limit == LONG_MIN) cmd.onepage_limit = 50; /* Figure out statistics to calculate. */ @@ -323,14 +320,14 @@ internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds) if (cmd.a_statistics[FRQ_ST_ALL]) stats |= frq_all; if (cmd.sort != FRQ_AVALUE && cmd.sort != FRQ_DVALUE) - stats &= ~frq_median; + stats &= ~BIT_INDEX (frq_median); for (i = 0; i < frq_n_stats; i++) if (cmd.a_statistics[st_name[i].st_indx]) stats |= BIT_INDEX (i); if (stats & frq_kurt) - stats |= frq_sekurt; + stats |= BIT_INDEX (frq_sekurt); if (stats & frq_skew) - stats |= frq_seskew; + stats |= BIT_INDEX (frq_seskew); /* Calculate n_stats. */ n_stats = 0; @@ -363,7 +360,14 @@ internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds) add_percentile (j / (double) cmd.n_ntiles[i]); } } - + if (stats & BIT_INDEX (frq_median)) + { + /* Treat the median as the 50% percentile. + We output it in the percentiles table as "50 (Median)." */ + add_percentile (0.5); + stats &= ~BIT_INDEX (frq_median); + n_stats--; + } /* Do it! */ input = casereader_create_filter_weight (proc_open (ds), dataset_dict (ds), @@ -372,12 +376,12 @@ internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds) for (; casegrouper_get_next_group (grouper, &group); casereader_destroy (group)) { - struct ccase c; + struct ccase *c; precalc (group, ds); - for (; casereader_read (group, &c); case_destroy (&c)) - calc (&c, ds); - postcalc (); + for (; (c = casereader_read (group)) != NULL; case_unref (c)) + calc (c, ds); + postcalc (ds); } ok = casegrouper_destroy (grouper); ok = proc_commit (ds) && ok; @@ -531,13 +535,15 @@ calc (const struct ccase *c, const struct dataset *ds) static void precalc (struct casereader *input, struct dataset *ds) { - struct ccase c; + struct ccase *c; size_t i; - if (!casereader_peek (input, 0, &c)) - return; - output_split_file_values (ds, &c); - case_destroy (&c); + c = casereader_peek (input, 0); + if (c != NULL) + { + output_split_file_values (ds, c); + case_unref (c); + } pool_destroy (data_pool); data_pool = pool_create (); @@ -554,8 +560,10 @@ precalc (struct casereader *input, struct dataset *ds) /* Finishes up with the variables after frequencies have been calculated. Displays statistics, percentiles, ... */ static void -postcalc (void) +postcalc (const struct dataset *ds) { + const struct dictionary *dict = dataset_dict (ds); + const struct variable *wv = dict_get_weight (dict); size_t i; for (i = 0; i < n_variables; i++) @@ -575,16 +583,16 @@ postcalc (void) switch (cmd.cond) { case FRQ_CONDENSE: - dump_condensed (v); + dump_condensed (v, wv); break; case FRQ_STANDARD: - dump_full (v); + dump_full (v, wv); break; case FRQ_ONEPAGE: if (n_categories > cmd.onepage_limit) - dump_condensed (v); + dump_condensed (v, wv); else - dump_full (v); + dump_full (v, wv); break; default: NOT_REACHED (); @@ -594,50 +602,45 @@ postcalc (void) /* Statistics. */ if (n_stats) - dump_statistics (v, !dumped_freq_tab); + dump_statistics (v, !dumped_freq_tab, wv); if ( chart == GFT_HIST) { double d[frq_n_stats]; - struct normal_curve norm; - gsl_histogram *hist ; - - - norm.N = vf->tab.valid_cases; + struct histogram *hist ; calc_stats (v, d); - norm.mean = d[frq_mean]; - norm.stddev = d[frq_stddev]; - hist = freq_tab_to_hist(ft,v); + hist = freq_tab_to_hist (ft,v); - histogram_plot(hist, var_to_string(v), &norm, normal); + histogram_plot_n (hist, var_to_string(v), + vf->tab.valid_cases, + d[frq_mean], + d[frq_stddev], + normal); - gsl_histogram_free(hist); + statistic_destroy ((struct statistic *)hist); } - if ( chart == GFT_PIE) { do_piechart(v_variables[i], ft); } - - cleanup_freq_tab (v); } } /* Returns the comparison function that should be used for - sorting a frequency table by FRQ_SORT using VAR_TYPE - variables. */ + sorting a frequency table by FRQ_SORT using VAL_TYPE + values. */ static hsh_compare_func * -get_freq_comparator (int frq_sort, enum var_type var_type) +get_freq_comparator (int frq_sort, enum val_type val_type) { - bool is_numeric = var_type == VAR_NUMERIC; + bool is_numeric = val_type == VAL_NUMERIC; switch (frq_sort) { case FRQ_AVALUE: @@ -761,7 +764,7 @@ frq_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_freque vf->groups = NULL; vf->width = var_get_width (v); vf->print = *var_get_print_format (v); - if (vf->width > MAX_SHORT_STRING && get_algorithm () == COMPATIBLE) + if (vf->width > MAX_SHORT_STRING && settings_get_algorithm () == COMPATIBLE) { enum fmt_type type = var_get_print_format (v)->type; vf->width = MAX_SHORT_STRING; @@ -876,11 +879,7 @@ add_percentile (double x) { percentiles = pool_nrealloc (syntax_pool, percentiles, n_percentiles + 1, sizeof *percentiles); - - if (i < n_percentiles) - memmove (&percentiles[i + 1], &percentiles[i], - (n_percentiles - i) * sizeof (struct percentile) ); - + insert_element (percentiles, n_percentiles, sizeof *percentiles, i); percentiles[i].p = x; n_percentiles++; } @@ -1033,8 +1032,9 @@ full_dim (struct tab_table *t, struct outp_driver *d) /* Displays a full frequency table for variable V. */ static void -dump_full (const struct variable *v) +dump_full (const struct variable *v, const struct variable *wv) { + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : &F_8_0; int n_categories; struct var_freqs *vf; struct freq_tab *ft; @@ -1103,10 +1103,10 @@ dump_full (const struct variable *v) } tab_value (t, 0 + lab, r, TAB_NONE, f->value, &vf->print); - tab_float (t, 1 + lab, r, TAB_NONE, f->count, 8, 0); - tab_float (t, 2 + lab, r, TAB_NONE, percent, 5, 1); - tab_float (t, 3 + lab, r, TAB_NONE, valid_percent, 5, 1); - tab_float (t, 4 + lab, r, TAB_NONE, cum_total, 5, 1); + tab_double (t, 1 + lab, r, TAB_NONE, f->count, wfmt); + tab_double (t, 2 + lab, r, TAB_NONE, percent, NULL); + tab_double (t, 3 + lab, r, TAB_NONE, valid_percent, NULL); + tab_double (t, 4 + lab, r, TAB_NONE, cum_total, NULL); r++; } for (; f < &ft->valid[n_categories]; f++) @@ -1121,9 +1121,9 @@ dump_full (const struct variable *v) } tab_value (t, 0 + lab, r, TAB_NONE, f->value, &vf->print); - tab_float (t, 1 + lab, r, TAB_NONE, f->count, 8, 0); - tab_float (t, 2 + lab, r, TAB_NONE, - f->count / ft->total_cases * 100.0, 5, 1); + tab_double (t, 1 + lab, r, TAB_NONE, f->count, wfmt); + tab_double (t, 2 + lab, r, TAB_NONE, + f->count / ft->total_cases * 100.0, NULL); tab_text (t, 3 + lab, r, TAB_NONE, _("Missing")); r++; } @@ -1135,9 +1135,9 @@ dump_full (const struct variable *v) tab_hline (t, TAL_2, 0, 4 + lab, r); tab_joint_text (t, 0, r, 0 + lab, r, TAB_RIGHT | TAT_TITLE, _("Total")); tab_vline (t, TAL_0, 1, r, r); - tab_float (t, 1 + lab, r, TAB_NONE, cum_freq, 8, 0); - tab_float (t, 2 + lab, r, TAB_NONE, 100.0, 5, 1); - tab_float (t, 3 + lab, r, TAB_NONE, 100.0, 5, 1); + tab_double (t, 1 + lab, r, TAB_NONE, cum_freq, wfmt); + tab_fixed (t, 2 + lab, r, TAB_NONE, 100.0, 5, 1); + tab_fixed (t, 3 + lab, r, TAB_NONE, 100.0, 5, 1); tab_title (t, "%s", var_to_string (v)); tab_submit (t); @@ -1164,8 +1164,9 @@ condensed_dim (struct tab_table *t, struct outp_driver *d) /* Display condensed frequency table for variable V. */ static void -dump_condensed (const struct variable *v) +dump_condensed (const struct variable *v, const struct variable *wv) { + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : &F_8_0; int n_categories; struct var_freqs *vf; struct freq_tab *ft; @@ -1196,17 +1197,17 @@ dump_condensed (const struct variable *v) cum_total += f->count / ft->valid_cases * 100.0; tab_value (t, 0, r, TAB_NONE, f->value, &vf->print); - tab_float (t, 1, r, TAB_NONE, f->count, 8, 0); - tab_float (t, 2, r, TAB_NONE, percent, 3, 0); - tab_float (t, 3, r, TAB_NONE, cum_total, 3, 0); + tab_double (t, 1, r, TAB_NONE, f->count, wfmt); + tab_double (t, 2, r, TAB_NONE, percent, NULL); + tab_double (t, 3, r, TAB_NONE, cum_total, NULL); r++; } for (; f < &ft->valid[n_categories]; f++) { tab_value (t, 0, r, TAB_NONE, f->value, &vf->print); - tab_float (t, 1, r, TAB_NONE, f->count, 8, 0); - tab_float (t, 2, r, TAB_NONE, - f->count / ft->total_cases * 100.0, 3, 0); + tab_double (t, 1, r, TAB_NONE, f->count, wfmt); + tab_double (t, 2, r, TAB_NONE, + f->count / ft->total_cases * 100.0, NULL); r++; } @@ -1236,28 +1237,9 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) double rank; int i = 0; int idx; - double *median_value; /* Calculate percentiles. */ - /* If the 50th percentile was not explicitly requested then we must - calculate it anyway --- it's the median */ - median_value = 0 ; - for (i = 0; i < n_percentiles; i++) - { - if (percentiles[i].p == 0.5) - { - median_value = &percentiles[i].value; - break; - } - } - - if ( 0 == median_value ) - { - add_percentile (0.5); - implicit_50th = 1; - } - for (i = 0; i < n_percentiles; i++) { percentiles[i].flag = 0; @@ -1275,7 +1257,7 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) double tp; if ( percentiles[i].flag2 ) continue ; - if ( get_algorithm() != COMPATIBLE ) + if ( settings_get_algorithm () != COMPATIBLE ) tp = (ft->valid_cases - 1) * percentiles[i].p; else @@ -1326,7 +1308,7 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) double s; double dummy; - if ( get_algorithm() != COMPATIBLE ) + if ( settings_get_algorithm () != COMPATIBLE ) { s = modf((ft->valid_cases - 1) * percentiles[i].p , &dummy); } @@ -1337,9 +1319,6 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) percentiles[i].value = percentiles[i].x1 + ( percentiles[i].x2 - percentiles[i].x1) * s ; - - if ( percentiles[i].p == 0.50) - median_value = &percentiles[i].value; } @@ -1376,7 +1355,6 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) d[frq_max] = ft->valid[ft->n_valid - 1].value[0].f; d[frq_mode] = X_mode; d[frq_range] = d[frq_max] - d[frq_min]; - d[frq_median] = *median_value; d[frq_sum] = d[frq_mean] * W; d[frq_stddev] = sqrt (d[frq_variance]); d[frq_semean] = d[frq_stddev] / sqrt (W); @@ -1386,18 +1364,15 @@ calc_stats (const struct variable *v, double d[frq_n_stats]) /* Displays a table of all the statistics requested for variable V. */ static void -dump_statistics (const struct variable *v, int show_varname) +dump_statistics (const struct variable *v, bool show_varname, + const struct variable *wv) { + const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : &F_8_0; struct freq_tab *ft; double stat_value[frq_n_stats]; struct tab_table *t; int i, r; - int n_explicit_percentiles = n_percentiles; - - if ( implicit_50th && n_percentiles > 0 ) - --n_percentiles; - if (var_is_alpha (v)) return; ft = &get_var_freqs (v)->tab; @@ -1409,7 +1384,7 @@ dump_statistics (const struct variable *v, int show_varname) } calc_stats (v, stat_value); - t = tab_create (3, n_stats + n_explicit_percentiles + 2, 0); + t = tab_create (3, n_stats + n_percentiles + 2, 0); tab_dim (t, tab_natural_dimensions); tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ; @@ -1425,7 +1400,7 @@ dump_statistics (const struct variable *v, int show_varname) { tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, gettext (st_name[i].s10)); - tab_float (t, 2, r, TAB_NONE, stat_value[i], 11, 3); + tab_double (t, 2, r, TAB_NONE, stat_value[i], NULL); r++; } @@ -1433,20 +1408,22 @@ dump_statistics (const struct variable *v, int show_varname) tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Valid")); tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("Missing")); - tab_float(t, 2, 0, TAB_NONE, ft->valid_cases, 11, 0); - tab_float(t, 2, 1, TAB_NONE, ft->total_cases - ft->valid_cases, 11, 0); - + tab_double (t, 2, 0, TAB_NONE, ft->valid_cases, wfmt); + tab_double (t, 2, 1, TAB_NONE, ft->total_cases - ft->valid_cases, wfmt); - for (i = 0; i < n_explicit_percentiles; i++, r++) + for (i = 0; i < n_percentiles; i++, r++) { if ( i == 0 ) { tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Percentiles")); } - tab_float (t, 1, r, TAB_LEFT, percentiles[i].p * 100, 3, 0 ); - tab_float (t, 2, r, TAB_NONE, percentiles[i].value, 11, 3); - + if (percentiles[i].p == 0.5) + tab_text (t, 1, r, TAB_LEFT, _("50 (Median)")); + else + tab_fixed (t, 1, r, TAB_LEFT, percentiles[i].p * 100, 3, 0); + tab_double (t, 2, r, TAB_NONE, percentiles[i].value, + var_get_print_format (v)); } tab_columns (t, SOM_COL_DOWN, 1); @@ -1461,14 +1438,14 @@ dump_statistics (const struct variable *v, int show_varname) /* Create a gsl_histogram from a freq_tab */ -gsl_histogram * -freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var) +struct histogram * +freq_tab_to_hist (const struct freq_tab *ft, const struct variable *var) { int i; double x_min = DBL_MAX; double x_max = -DBL_MAX; - gsl_histogram *hist; + struct statistic *hist; const double bins = 11; struct hsh_iterator hi; @@ -1485,15 +1462,15 @@ freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var) if ( frq->value[0].f > x_max ) x_max = frq->value[0].f ; } - hist = histogram_create(bins, x_min, x_max); + hist = histogram_create (bins, x_min, x_max); for( i = 0 ; i < ft->n_valid ; ++i ) { frq = &ft->valid[i]; - gsl_histogram_accumulate(hist, frq->value[0].f, frq->count); + histogram_add ((struct histogram *)hist, frq->value[0].f, frq->count); } - return hist; + return (struct histogram *)hist; } @@ -1523,7 +1500,8 @@ freq_tab_to_slice_array(const struct freq_tab *frq_tab, { const struct freq *frq = &frq_tab->valid[i]; - slices[i].label = var_get_value_name (var, frq->value); + ds_init_empty (&slices[i].label); + var_append_value_name (var, frq->value, &slices[i].label); slices[i].magnetude = frq->count; } @@ -1537,12 +1515,17 @@ static void do_piechart(const struct variable *var, const struct freq_tab *frq_tab) { struct slice *slices; - int n_slices; + int n_slices, i; slices = freq_tab_to_slice_array(frq_tab, var, &n_slices); piechart_plot(var_to_string(var), slices, n_slices); + for (i = 0 ; i < n_slices ; ++i ) + { + ds_destroy (&slices[i].label); + } + free(slices); }