X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fcrosstabs.q;h=08a182a456a4836d61d1fa9d2f847921f8ae97d3;hb=bc37c3f489947cf081a930a5d4e58dbd133eb563;hp=ab73f96ad5bea6b37bb481b488b39fdf33c79202;hpb=3fe5cc7ed8d6fd1951f016a794415a00ea4059a2;p=pspp diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index ab73f96ad5..08a182a456 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -1,5 +1,5 @@ /* 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 @@ -74,6 +74,8 @@ *^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, @@ -182,6 +184,11 @@ struct crosstabs_proc 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. */ @@ -200,6 +207,12 @@ static void tabulate_integer_case (struct pivot_table *, const struct ccase *, 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) @@ -236,6 +249,10 @@ 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; @@ -316,6 +333,12 @@ cmd_crosstabs (struct lexer *lexer, struct dataset *ds) { 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) @@ -408,10 +431,7 @@ crs_custom_tables (struct lexer *lexer, struct dataset *ds, if (!lex_match (lexer, T_BY)) { if (n_by < 2) - { - lex_force_match (lexer, T_BY); - goto done; - } + goto done; else break; } @@ -517,7 +537,7 @@ crs_custom_variables (struct lexer *lexer, struct dataset *ds, 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)); @@ -570,7 +590,7 @@ should_tabulate_case (const struct pivot_table *pt, const struct ccase *c, 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; } } @@ -680,17 +700,36 @@ static bool find_crosstab (struct pivot_table *, size_t *row0p, size_t *row1p); 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); @@ -704,7 +743,8 @@ postcalc (struct crosstabs_proc *proc) 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); @@ -719,15 +759,14 @@ postcalc (struct crosstabs_proc *proc) } } 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 @@ -737,7 +776,7 @@ postcalc (struct crosstabs_proc *proc) 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)) @@ -749,7 +788,7 @@ postcalc (struct crosstabs_proc *proc) } } - 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); } @@ -2633,7 +2672,7 @@ calc_symmetric (struct crosstabs_proc *proc, struct pivot_table *pt, + 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)