X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffrequencies.q;h=acfeed86d3c65e2327e2b364def9b0778df614d9;hb=5156fa5a8323a16f6b4bbc8950221cdc1d0e023d;hp=8393819c0a0d2bda5a33eb722ac8267a1e3945b0;hpb=b321086267ad1014dc5d09886396cde30f094437;p=pspp-builds.git diff --git a/src/frequencies.q b/src/frequencies.q index 8393819c..acfeed86 100644 --- a/src/frequencies.q +++ b/src/frequencies.q @@ -27,6 +27,8 @@ #include "error.h" #include #include +#include + #include "alloc.h" #include "bitvector.h" #include "case.h" @@ -188,6 +190,49 @@ static struct variable **v_variables; static struct pool *int_pool; /* Integer mode. */ static struct pool *gen_pool; /* General mode. */ +/* Frequency tables. */ + +/* Frequency table entry. */ +struct freq + { + union value v; /* The value. */ + double c; /* The number of occurrences of the value. */ + }; + +/* Types of frequency tables. */ +enum + { + FRQM_GENERAL, + FRQM_INTEGER + }; + +/* Entire frequency table. */ +struct freq_tab + { + int mode; /* FRQM_GENERAL or FRQM_INTEGER. */ + + /* General mode. */ + struct hsh_table *data; /* Undifferentiated data. */ + + /* Integer mode. */ + double *vector; /* Frequencies proper. */ + int min, max; /* The boundaries of the table. */ + double out_of_range; /* Sum of weights of out-of-range values. */ + double sysmis; /* Sum of weights of SYSMIS values. */ + + /* All modes. */ + struct freq *valid; /* Valid freqs. */ + int n_valid; /* Number of total freqs. */ + + struct freq *missing; /* Missing freqs. */ + int n_missing; /* Number of missing freqs. */ + + /* Statistics. */ + double total_cases; /* Sum of weights of all cases. */ + double valid_cases; /* Sum of weights of valid cases. */ + }; + + /* Per-variable frequency data. */ struct var_freqs { @@ -229,6 +274,15 @@ static hsh_compare_func compare_value_numeric_a, compare_value_alpha_a; static hsh_compare_func compare_value_numeric_d, compare_value_alpha_d; static hsh_compare_func compare_freq_numeric_a, compare_freq_alpha_a; 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 * +freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var); + + /* Parser and outline. */ @@ -319,6 +373,8 @@ internal_cmd_frequencies (void) /* Do it! */ procedure_with_splits (precalc, calc, postcalc, NULL); + free_frequencies(&cmd); + return CMD_SUCCESS; } @@ -573,31 +629,28 @@ postcalc (void *aux UNUSED) if ( chart == GFT_HIST) { - struct chart ch; double d[frq_n_stats]; - struct normal_curve norm; - norm.N = vf->tab.total_cases; + gsl_histogram *hist ; + + + norm.N = vf->tab.valid_cases; calc_stats(v,d); norm.mean = d[frq_mean]; norm.stddev = d[frq_stddev]; - chart_initialise(&ch); - draw_histogram(&ch, v_variables[i], ft, "HISTOGRAM",&norm,normal); - chart_finalise(&ch); + hist = freq_tab_to_hist(ft,v); + + histogram_plot(hist, var_to_string(v), &norm, normal); + + gsl_histogram_free(hist); } if ( chart == GFT_PIE) { - struct chart ch; - - chart_initialise(&ch); - - draw_piechart(&ch, v_variables[i], ft); - - chart_finalise(&ch); + do_piechart(v_variables[i], ft); } @@ -1484,6 +1537,94 @@ dump_statistics (struct variable *v, int show_varname) tab_submit (t); } + + +/* Create a gsl_histogram from a freq_tab */ +gsl_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; + const double bins = 11; + + struct hsh_iterator hi; + struct hsh_table *fh = ft->data; + struct freq *frq; + + /* Find out the extremes of the x value */ + for ( frq = hsh_first(fh, &hi); frq != 0; frq = hsh_next(fh, &hi) ) + { + if ( is_missing(&frq->v, var)) + continue; + + if ( frq->v.f < x_min ) x_min = frq->v.f ; + if ( frq->v.f > x_max ) x_max = frq->v.f ; + } + + 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->v.f, frq->c); + } + + return hist; +} + + +static struct slice * +freq_tab_to_slice_array(const struct freq_tab *frq_tab, + const struct variable *var, + int *n_slices); + + +/* Allocate an array of slices and fill them from the data in frq_tab + 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 freq_tab *frq_tab, + const struct variable *var, + int *n_slices) +{ + int i; + struct slice *slices; + + *n_slices = frq_tab->n_valid; + + slices = xmalloc ( *n_slices * sizeof (struct slice ) ); + + for (i = 0 ; i < *n_slices ; ++i ) + { + const struct freq *frq = &frq_tab->valid[i]; + + slices[i].label = value_to_string(&frq->v, var); + + slices[i].magnetude = frq->c; + } + + return slices; +} + + + +static void +do_piechart(const struct variable *var, const struct freq_tab *frq_tab) +{ + struct slice *slices; + int n_slices; + + slices = freq_tab_to_slice_array(frq_tab, var, &n_slices); + + piechart_plot(var_to_string(var), slices, n_slices); + + free(slices); +} + /* Local Variables: mode: c