/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2016 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
*^tables=custom;
+variables=custom;
missing=miss:!table/include/report;
+ count=roundwhat:asis/case/!cell,
+ roundhow:!round/truncate;
+write[wr_]=none,cells,all;
+format=val:!avalue/dvalue,
indx:!noindex/index,
unsigned int cells; /* Bit k is 1 if cell k is requested. */
int a_cells[CRS_CL_count]; /* 0...n_cells-1 are the requested cells. */
+ /* Rounding of cells. */
+ bool round_case_weights; /* Round case weights? */
+ bool round_cells; /* If !round_case_weights, round cells? */
+ bool round_down; /* Round down? (otherwise to nearest) */
+
/* STATISTICS. */
unsigned int statistics; /* Bit k is 1 if statistic k is requested. */
static void postcalc (struct crosstabs_proc *);
static void submit (struct pivot_table *, struct tab_table *);
+static double
+round_weight (const struct crosstabs_proc *proc, double weight)
+{
+ return proc->round_down ? floor (weight) : floor (weight + 0.5);
+}
+
/* Parses and executes the CROSSTABS procedure. */
int
cmd_crosstabs (struct lexer *lexer, struct dataset *ds)
proc.descending = cmd.val == CRS_DVALUE;
+ proc.round_case_weights = cmd.sbc_count && cmd.roundwhat == CRS_CASE;
+ proc.round_cells = cmd.sbc_count && cmd.roundwhat == CRS_CELL;
+ proc.round_down = cmd.roundhow == CRS_TRUNCATE;
+
/* CELLS. */
if (!cmd.sbc_cells)
proc.cells = 1u << CRS_CL_COUNT;
{
double weight = dict_get_case_weight (dataset_dict (ds), c,
&proc.bad_warn);
+ if (cmd.roundwhat == CRS_CASE)
+ {
+ weight = round_weight (&proc, weight);
+ if (weight == 0.)
+ continue;
+ }
if (should_tabulate_case (pt, c, proc.exclude))
{
if (proc.mode == GENERAL)
if (!lex_match (lexer, T_BY))
{
if (n_by < 2)
- {
- lex_force_match (lexer, T_BY);
- goto done;
- }
+ goto done;
else
break;
}
vr->var = var;
vr->min = min;
- vr->max = max + 1.;
+ vr->max = max;
vr->count = max - min + 1;
hmap_insert (&proc->var_ranges, &vr->hmap_node,
hash_pointer (var, 0));
if (range != NULL)
{
double num = case_num (c, var);
- if (num < range->min || num > range->max)
+ if (num < range->min || num >= range->max + 1.)
return false;
}
}
static void
postcalc (struct crosstabs_proc *proc)
{
- struct pivot_table *pt;
+
+ /* Round hash table entries, if requested
+
+ If this causes any of the cell counts to fall to zero, delete those
+ cells. */
+ if (proc->round_cells)
+ for (struct pivot_table *pt = proc->pivots;
+ pt < &proc->pivots[proc->n_pivots]; pt++)
+ {
+ struct freq *e, *next;
+ HMAP_FOR_EACH_SAFE (e, next, struct freq, node, &pt->data)
+ {
+ e->count = round_weight (proc, e->count);
+ if (e->count == 0.0)
+ {
+ hmap_delete (&pt->data, &e->node);
+ free (e);
+ }
+ }
+ }
/* Convert hash tables into sorted arrays of entries. */
- for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++)
+ for (struct pivot_table *pt = proc->pivots;
+ pt < &proc->pivots[proc->n_pivots]; pt++)
{
struct freq *e;
- size_t i;
pt->n_entries = hmap_count (&pt->data);
pt->entries = xnmalloc (pt->n_entries, sizeof *pt->entries);
- i = 0;
+ size_t i = 0;
HMAP_FOR_EACH (e, struct freq, node, &pt->data)
pt->entries[i++] = e;
hmap_destroy (&pt->data);
make_summary_table (proc);
/* Output each pivot table. */
- for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++)
+ for (struct pivot_table *pt = proc->pivots;
+ pt < &proc->pivots[proc->n_pivots]; pt++)
{
if (proc->pivot || pt->n_vars == 2)
output_pivot_table (proc, pt);
}
}
if (proc->barchart)
- chart_item_submit
- (barchart_create (pt->vars, pt->n_vars, _("Count"), pt->entries, pt->n_entries));
+ chart_item_submit
+ (barchart_create (pt->vars, pt->n_vars, _("Count"), false, pt->entries, pt->n_entries));
}
/* Free output and prepare for next split file. */
- for (pt = &proc->pivots[0]; pt < &proc->pivots[proc->n_pivots]; pt++)
+ for (struct pivot_table *pt = proc->pivots;
+ pt < &proc->pivots[proc->n_pivots]; pt++)
{
- size_t i;
-
pt->missing = 0.0;
/* Free the members that were allocated in this function(and the values
lower level (in output_pivot_table), or both allocated and destroyed
at a higher level (in crs_custom_tables and free_proc,
respectively). */
- for (i = 0; i < pt->n_vars; i++)
+ for (size_t i = 0; i < pt->n_vars; i++)
{
int width = var_get_width (pt->vars[i]);
if (value_needs_init (width))
}
}
- for (i = 0; i < pt->n_entries; i++)
+ for (size_t i = 0; i < pt->n_entries; i++)
free (pt->entries[i]);
free (pt->entries);
}
/* Cohen's kappa. */
if (proc->statistics & (1u << CRS_ST_KAPPA) && pt->ns_rows == pt->ns_cols)
{
+ double ase_under_h0;
double sum_fii, sum_rici, sum_fiiri_ci, sum_fijri_ci2, sum_riciri_ci;
int i, j;
v[8] = (pt->total * sum_fii - sum_rici) / (pow2 (pt->total) - sum_rici);
- ase[8] = sqrt ((pow2 (pt->total) * sum_rici
- + sum_rici * sum_rici
- - pt->total * sum_riciri_ci)
- / (pt->total * (pow2 (pt->total) - sum_rici) * (pow2 (pt->total) - sum_rici)));
-#if 0
- t[8] = v[8] / sqrt (pt->total * (((sum_fii * (pt->total - sum_fii))
+ ase_under_h0 = sqrt ((pow2 (pt->total) * sum_rici
+ + sum_rici * sum_rici
+ - pt->total * sum_riciri_ci)
+ / (pt->total * (pow2 (pt->total) - sum_rici) * (pow2 (pt->total) - sum_rici)));
+
+ ase[8] = sqrt (pt->total * (((sum_fii * (pt->total - sum_fii))
/ pow2 (pow2 (pt->total) - sum_rici))
+ ((2. * (pt->total - sum_fii)
* (2. * sum_fii * sum_rici
- pt->total * sum_fiiri_ci))
- / cube (pow2 (pt->total) - sum_rici))
+ / pow3 (pow2 (pt->total) - sum_rici))
+ (pow2 (pt->total - sum_fii)
* (pt->total * sum_fijri_ci2 - 4.
* sum_rici * sum_rici)
/ pow4 (pow2 (pt->total) - sum_rici))));
-#else
- t[8] = v[8] / ase[8];
-#endif
+
+ t[8] = v[8] / ase_under_h0;
}
return 1;