You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/*
TODO:
#include "error.h"
#include <math.h>
#include <stdlib.h>
+#include <gsl/gsl_histogram.h>
+
#include "alloc.h"
#include "bitvector.h"
#include "case.h"
#include "vfm.h"
#include "settings.h"
#include "chart.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
/* (headers) */
#include "debug-print.h"
static int normal; /* FIXME */
/* Variables for which to calculate statistics. */
-static int n_variables;
+static size_t n_variables;
static struct variable **v_variables;
/* Arenas used to store semi-permanent storage. */
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
{
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);
+
+
\f
/* Parser and outline. */
/* Do it! */
procedure_with_splits (precalc, calc, postcalc, NULL);
+ free_frequencies(&cmd);
+
return CMD_SUCCESS;
}
calc (struct ccase *c, void *aux UNUSED)
{
double weight;
- int i;
+ size_t i;
int bad_warn = 1;
weight = dict_get_case_weight (default_dict, c, &bad_warn);
static void
precalc (void *aux UNUSED)
{
- int i;
+ size_t i;
pool_destroy (gen_pool);
gen_pool = pool_create ();
static void
postcalc (void *aux UNUSED)
{
- int i;
+ size_t i;
for (i = 0; i < n_variables; i++)
{
dump_statistics (v, !dumped_freq_tab);
+
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);
}
+
cleanup_freq_tab (v);
}
const struct freq *f = f_;
struct variable *v = v_;
- return !is_missing (&f->v, v);
+ return !mv_is_value_missing (&v->miss, &f->v);
}
/* Summarizes the frequency table data for variable V. */
hsh_compare_func *compare;
struct freq_tab *ft;
size_t count;
- void **data;
+ void *const *data;
struct freq *freqs, *f;
size_t i;
data = hsh_data (ft->data);
/* Copy dereferenced data into freqs. */
- freqs = xmalloc (count * sizeof *freqs);
+ freqs = xnmalloc (count, sizeof *freqs);
for (i = 0; i < count; i++)
{
struct freq *f = data[i];
int mode;
int min = 0, max = 0;
- int old_n_variables = n_variables;
- int i;
+ size_t old_n_variables = n_variables;
+ size_t i;
lex_match ('=');
if (token != T_ALL && (token != T_ID
{
vf->tab.min = min;
vf->tab.max = max;
- vf->tab.vector = pool_alloc (int_pool,
- sizeof (struct freq) * (max - min + 1));
+ vf->tab.vector = pool_nalloc (int_pool,
+ max - min + 1, sizeof *vf->tab.vector);
}
else
vf->tab.vector = NULL;
|| token == T_ID)
for (;;)
{
- int i;
+ size_t i;
/* Max, current size of list; list itself. */
int nl, ml;
double *dl;
/* Variable list. */
- int n;
+ size_t n;
struct variable **v;
if (!parse_variables (default_dict, &v, &n,
{
nl = ml = 0;
dl = NULL;
- while (token == T_NUM)
+ while (lex_integer ())
{
if (nl >= ml)
{
ml += 16;
- dl = pool_realloc (int_pool, dl, ml * sizeof (double));
+ dl = pool_nrealloc (int_pool, dl, ml, sizeof *dl);
}
dl[nl++] = tokval;
lex_get ();
if (i >= n_percentiles || tokval != percentiles[i].p)
{
- percentiles
- = pool_realloc (int_pool, percentiles,
- (n_percentiles + 1) * sizeof (struct percentile ));
+ percentiles = pool_nrealloc (int_pool, percentiles,
+ n_percentiles + 1, sizeof *percentiles);
if (i < n_percentiles)
memmove (&percentiles[i + 1], &percentiles[i],
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 ( mv_is_value_missing(&var->miss, &frq->v))
+ 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 = xnmalloc (*n_slices, sizeof *slices);
+
+ 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