/*
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
#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"
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);
}
int n_stats;
/* Histogram and pie chart settings. */
- struct frq_chart *hist, *pie;
+ struct frq_chart *hist, *pie, *bar;
};
const struct variable *var,
const struct freq_tab *frq_tab);
+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);
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;
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);
}
}
double pie_max = DBL_MAX;
bool pie_missing = false;
+ double bar_min = -DBL_MAX;
+ double bar_max = DBL_MAX;
+ bool bar_freq = true;
+
double hi_min = -DBL_MAX;
double hi_max = DBL_MAX;
int hi_scale = FRQ_FREQ;
frq.hist = NULL;
frq.pie = NULL;
+ frq.bar = NULL;
/* Accept an optional, completely pointless "/VARIABLES=" */
if (lex_match_id (lexer, "STATISTICS"))
{
- lex_match (lexer, T_EQUALS);
-
- frq.stats = 0;
- frq.n_stats = 0;
+ 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;
+
+ if (lex_match (lexer, T_EQUALS))
+ {
+ frq.n_stats = 0;
+ frq.stats = 0;
+ }
while (lex_token (lexer) != T_ENDCMD
&& lex_token (lexer) != T_SLASH)
lex_error (lexer, NULL);
goto error;
}
+ lex_match (lexer, T_COMMA);
}
}
else if (lex_match_id (lexer, "FORMAT"))
}
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"))
+ {
+ lex_force_match (lexer, T_LPAREN);
+ if (lex_force_num (lexer))
+ {
+ bar_min = lex_number (lexer);
+ lex_get (lexer);
+ }
+ lex_force_match (lexer, T_RPAREN);
+ }
+ else if (lex_match_id (lexer, "MAXIMUM"))
+ {
+ lex_force_match (lexer, T_LPAREN);
+ if (lex_force_num (lexer))
+ {
+ bar_max = lex_number (lexer);
+ lex_get (lexer);
+ }
+ lex_force_match (lexer, T_RPAREN);
+ }
+ else if (lex_match_id (lexer, "FREQ"))
+ {
+ if ( lex_match (lexer, T_LPAREN))
+ {
+ if (lex_force_num (lexer))
+ {
+ lex_number (lexer);
+ lex_get (lexer);
+ }
+ lex_force_match (lexer, T_RPAREN);
+ }
+ 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);
+ }
+ lex_force_match (lexer, T_RPAREN);
+ }
+ 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);
}
}
- if (frq.stats & FRQ_ST_MEDIAN)
+ if (frq.stats & BIT_INDEX (FRQ_ST_MEDIAN))
{
frq.percentiles =
xrealloc (frq.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;
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 = true;
+ frq.bar->y_scale = bar_freq ? FRQ_FREQ : FRQ_PERCENT;
+ }
+
if (sbc_piechart)
{
struct frq_chart *pie;
The caller is responsible for freeing slices
*/
static struct slice *
-freq_tab_to_slice_array(const struct frq_chart *pie,
+freq_tab_to_slice_array(const struct frq_chart *catchart,
const struct freq_tab *frq_tab,
const struct variable *var,
int *n_slicesp)
struct slice *slices;
int n_slices;
int i;
+ double total = 0;
slices = xnmalloc (frq_tab->n_valid + frq_tab->n_missing, sizeof *slices);
n_slices = 0;
+
for (i = 0; i < frq_tab->n_valid; i++)
- n_slices += add_slice (pie, &frq_tab->valid[i], var, &slices[n_slices]);
+ {
+ const struct freq *f = &frq_tab->valid[i];
+ total += f->count;
+ if (f->count > catchart->x_max)
+ continue;
+
+ if (f->count < catchart->x_min)
+ continue;
+
+ n_slices += add_slice (catchart, f, var, &slices[n_slices]);
+ }
+
+ if (catchart->y_scale == FRQ_PERCENT)
+ for (i = 0; i < frq_tab->n_valid; i++)
+ {
+ slices[i].magnitude /= total;
+ slices[i].magnitude *= 100.00;
+ }
+
for (i = 0; i < frq_tab->n_missing; i++)
- n_slices += add_slice (pie, &frq_tab->missing[i], var, &slices[n_slices]);
+ n_slices += add_slice (catchart, &frq_tab->missing[i], var, &slices[n_slices]);
*n_slicesp = n_slices;
return slices;
free (slices);
}
+
+static void
+do_barchart(const struct frq_chart *bar, const struct variable *var,
+ const struct freq_tab *frq_tab)
+{
+ struct slice *slices;
+ int n_slices, i;
+
+ slices = freq_tab_to_slice_array (bar, frq_tab, var, &n_slices);
+
+ chart_item_submit (barchart_create (var_to_string (var),
+ (bar->y_scale == FRQ_FREQ) ? _("Count") : _("Percent"),
+ slices, n_slices));
+
+ for (i = 0; i < n_slices; i++)
+ ds_destroy (&slices[i].label);
+ free (slices);
+}
+
+
/* Calculates all the pertinent statistics for VF, putting them in array
D[]. */
static void
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)
&d[FRQ_ST_SKEWNESS], &d[FRQ_ST_KURTOSIS]);
moments_destroy (m);
- /* Formulas below are taken from _SPSS Statistical Algorithms_. */
+ /* Formulae 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;
d[FRQ_ST_MODE] = X_mode;
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)
{
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++;
}
}
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));