1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2009, 2010, 2011, 2014 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "language/stats/binomial.h"
22 #include <gsl/gsl_cdf.h>
23 #include <gsl/gsl_randist.h>
25 #include "data/case.h"
26 #include "data/casereader.h"
27 #include "data/dataset.h"
28 #include "data/dictionary.h"
29 #include "data/format.h"
30 #include "data/value-labels.h"
31 #include "data/value.h"
32 #include "data/variable.h"
33 #include "language/stats/freq.h"
34 #include "libpspp/assertion.h"
35 #include "libpspp/compiler.h"
36 #include "libpspp/message.h"
37 #include "libpspp/misc.h"
38 #include "output/pivot-table.h"
40 #include "gl/xalloc.h"
41 #include "gl/minmax.h"
44 #define N_(msgid) msgid
45 #define _(msgid) gettext (msgid)
47 static double calculate_binomial_internal (double n1, double n2,
52 swap (double *i1, double *i2)
60 calculate_binomial (double n1, double n2, double p)
62 const double n = n1 + n2;
63 const bool test_reversed = (n1 / n > p) ;
70 return calculate_binomial_internal (n1, n2, p);
74 calculate_binomial_internal (double n1, double n2, double p)
76 /* SPSS Statistical Algorithms has completely different and WRONG
79 double sig1tailed = gsl_cdf_binomial_P (n1, p, n1 + n2);
82 return sig1tailed > 0.5 ? 1.0 :sig1tailed * 2.0;
88 do_binomial (const struct dictionary *dict,
89 struct casereader *input,
90 const struct one_sample_test *ost,
96 const struct binomial_test *bst = UP_CAST (ost, const struct binomial_test, parent);
101 for (; (c = casereader_read (input)) != NULL; case_unref (c))
104 double w = dict_get_case_weight (dict, c, &warn);
106 for (v = 0 ; v < ost->n_vars ; ++v)
108 const struct variable *var = ost->vars[v];
109 double value = case_num (c, var);
111 if (var_is_num_missing (var, value) & exclude)
114 if (bst->cutpoint != SYSMIS)
116 if (cat1[v].values[0].f >= value)
123 if (SYSMIS == cat1[v].values[0].f)
125 cat1[v].values[0].f = value;
128 else if (cat1[v].values[0].f == value)
130 else if (SYSMIS == cat2[v].values[0].f)
132 cat2[v].values[0].f = value;
135 else if (cat2[v].values[0].f == value)
137 else if (bst->category1 == SYSMIS)
138 msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
142 return casereader_destroy (input);
148 binomial_execute (const struct dataset *ds,
149 struct casereader *input,
150 enum mv_class exclude,
151 const struct npar_test *test,
155 const struct dictionary *dict = dataset_dict (ds);
156 const struct one_sample_test *ost = UP_CAST (test, const struct one_sample_test, parent);
157 const struct binomial_test *bst = UP_CAST (ost, const struct binomial_test, parent);
162 assert ((bst->category1 == SYSMIS) == (bst->category2 == SYSMIS) || bst->cutpoint != SYSMIS);
164 for (i = 0; i < 2; i++)
168 value = bst->cutpoint != SYSMIS ? bst->cutpoint : bst->category1;
170 value = bst->category2;
172 cat[i] = xnmalloc (ost->n_vars, sizeof *cat[i]);
173 for (size_t v = 0; v < ost->n_vars; v++)
175 cat[i][v].values[0].f = value;
180 if (do_binomial (dataset_dict (ds), input, ost, cat[0], cat[1], exclude))
182 struct pivot_table *table = pivot_table_create (N_("Binomial Test"));
183 pivot_table_set_weight_var (table, dict_get_weight (dict));
185 pivot_dimension_create (
186 table, PIVOT_AXIS_COLUMN, N_("Statistics"),
188 N_("N"), PIVOT_RC_COUNT,
189 N_("Observed Prop."), PIVOT_RC_OTHER,
190 N_("Test Prop."), PIVOT_RC_OTHER,
192 ? N_("Exact Sig. (2-tailed)")
193 : N_("Exact Sig. (1-tailed)")), PIVOT_RC_SIGNIFICANCE);
195 pivot_dimension_create (table, PIVOT_AXIS_ROW, N_("Groups"),
196 N_("Group 1"), N_("Group 2"), N_("Total"));
198 struct pivot_dimension *variables = pivot_dimension_create (
199 table, PIVOT_AXIS_ROW, N_("Variables"));
201 for (size_t v = 0; v < ost->n_vars; ++v)
203 const struct variable *var = ost->vars[v];
205 int var_idx = pivot_category_create_leaf (
206 variables->root, pivot_value_new_variable (var));
209 if (bst->cutpoint != SYSMIS)
211 table, 0, 0, var_idx,
212 pivot_value_new_user_text_nocopy (
213 xasprintf ("<= %.*g", DBL_DIG + 1, bst->cutpoint)));
215 for (int i = 0; i < 2; i++)
217 table, 0, i, var_idx,
218 pivot_value_new_var_value (var, cat[i][v].values));
220 double n_total = cat[0][v].count + cat[1][v].count;
221 double sig = calculate_binomial (cat[0][v].count, cat[1][v].count,
231 { 1, 0, cat[0][v].count },
232 { 1, 1, cat[1][v].count },
235 { 2, 0, cat[0][v].count / n_total },
236 { 2, 1, cat[1][v].count / n_total },
243 for (size_t i = 0; i < sizeof entries / sizeof *entries; i++)
245 const struct entry *e = &entries[i];
246 pivot_table_put3 (table, e->stat_idx, e->group_idx,
247 var_idx, pivot_value_new_number (e->x));
251 pivot_table_submit (table);
254 for (i = 0; i < 2; i++)