Binomial tests can now be specified by a cutpoint.
authorJohn Darrington <john@darrington.wattle.id.au>
Fri, 3 Apr 2009 10:16:57 +0000 (18:16 +0800)
committerJohn Darrington <john@darrington.wattle.id.au>
Fri, 3 Apr 2009 10:16:57 +0000 (18:16 +0800)
This change extends the NPAR TEST /BINOMIAL subcommand
so that binomial tests can be specified by cutpoint.
The manual had previously, incorrectly stated that this
was supported.  Now it actually is.  Fixes bug #26056

src/language/stats/binomial.c
src/language/stats/npar.q
tests/command/npar-binomial.sh

index b62b4dce1375a11c11030ca299de2284141261b9..b7b672ef682b651ca5d737b5b862761456577afe 100644 (file)
@@ -114,22 +114,32 @@ do_binomial (const struct dictionary *dict,
          if (var_is_value_missing (var, value, exclude))
            continue;
 
-         if ( NULL == cat1[v].value )
+         if (bst->cutpoint != SYSMIS)
            {
-             cat1[v].value = value_dup (value, width);
-             cat1[v].count = w;
+             if ( compare_values_short (cat1[v].value, value, var) >= 0 )
+                 cat1[v].count  += w;
+             else
+                 cat2[v].count += w;
            }
-         else if ( 0 == compare_values_short (cat1[v].value, value, var))
-           cat1[v].count += w;
-         else if ( NULL == cat2[v].value )
+         else
            {
-             cat2[v].value = value_dup (value, width);
-             cat2[v].count = w;
+             if ( NULL == cat1[v].value )
+               {
+                 cat1[v].value = value_dup (value, width);
+                 cat1[v].count = w;
+               }
+             else if ( 0 == compare_values_short (cat1[v].value, value, var))
+               cat1[v].count += w;
+             else if ( NULL == cat2[v].value )
+               {
+                 cat2[v].value = value_dup (value, width);
+                 cat2[v].count = w;
+               }
+             else if ( 0 == compare_values_short (cat2[v].value, value, var))
+               cat2[v].count += w;
+             else if ( bst->category1 == SYSMIS)
+               msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
            }
-         else if ( 0 == compare_values_short (cat2[v].value, value, var))
-           cat2[v].count += w;
-         else if ( bst->category1 == SYSMIS)
-           msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
        }
 
       case_unref (c);
@@ -154,9 +164,17 @@ binomial_execute (const struct dataset *ds,
   struct freq_mutable *cat1 = xzalloc (sizeof (*cat1) * ost->n_vars);
   struct freq_mutable *cat2 = xzalloc (sizeof (*cat1) * ost->n_vars);
 
-  assert ((bst->category1 == SYSMIS) == (bst->category2 == SYSMIS) );
+  assert ((bst->category1 == SYSMIS) == (bst->category2 == SYSMIS) || bst->cutpoint != SYSMIS);
 
-  if ( bst->category1 != SYSMIS )
+  if ( bst->cutpoint != SYSMIS )
+    {
+      int i;
+      union value v;
+      v.f = bst->cutpoint;
+      for (i = 0; i < ost->n_vars; i++)
+       cat1[i].value = value_dup (&v, 0);
+    }
+  else  if ( bst->category1 != SYSMIS )
     {
       int i;
       union value v;
@@ -197,8 +215,15 @@ binomial_execute (const struct dataset *ds,
          ds_init_empty (&catstr1);
          ds_init_empty (&catstr2);
 
-         var_append_value_name (var, cat1[v].value, &catstr1);
-         var_append_value_name (var, cat2[v].value, &catstr2);
+         if ( bst->cutpoint != SYSMIS)
+           {
+             ds_put_format (&catstr1, "<= %g", bst->cutpoint);
+           }
+         else
+           {
+             var_append_value_name (var, cat1[v].value, &catstr1);
+             var_append_value_name (var, cat2[v].value, &catstr2);
+           }
 
           tab_hline (table, TAL_1, 0, tab_nc (table) -1, 1 + v * 3);
 
index 34e03677dc9bc145568a910c05a1ea83a063d4e5..4caa112aefe8895555add598c773518078f5415d 100644 (file)
@@ -356,27 +356,24 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds,
            {
              lex_force_num (lexer);
              btp->category1 = lex_number (lexer);
-             lex_get (lexer);
-             if ( ! lex_force_match (lexer, ',')) return 2;
-             if ( ! lex_force_num (lexer) ) return 2;
-             btp->category2 = lex_number (lexer);
-             lex_get (lexer);
+             lex_get (lexer);
+             if ( lex_match (lexer, ','))
+               {
+                 if ( ! lex_force_num (lexer) ) return 2;
+                 btp->category2 = lex_number (lexer);
+                 lex_get (lexer);
+               }
+             else
+               {
+                 btp->cutpoint = btp->category1;
+               }
+
              lex_force_match (lexer, ')');
            }
        }
       else
        return 2;
     }
-  else
-    {
-      if ( lex_match (lexer, '(') )
-       {
-         lex_force_num (lexer);
-         btp->cutpoint = lex_number (lexer);
-         lex_get (lexer);
-         lex_force_match (lexer, ')');
-       }
-    }
 
   specs->n_tests++;
   specs->test = pool_realloc (specs->pool,
index 63696929faab2dedaba7db74e95bec3a4e7a8946..29ad2fab86f90558f692cefbd5a26d1b1502058e 100755 (executable)
@@ -208,6 +208,36 @@ WEIGHT BY w.
 NPAR TESTS
        /BINOMIAL(0.5) = x
        .
+
+ECHO 'P == 0.5; N1/N2 == 1 Cutpoint' .
+
+DATA LIST LIST NOTABLE /x * w *.
+BEGIN DATA.
+9    3
+10   7
+11   16
+END DATA.
+
+WEIGHT BY w.
+
+NPAR TESTS
+       /BINOMIAL(0.5) = x (10)
+       .
+
+ECHO 'P == 0.5; N1/N2 == 1 Named values' .
+
+DATA LIST LIST NOTABLE /x * w *.
+BEGIN DATA.
+10   10
+15   45
+20   13
+END DATA.
+
+WEIGHT BY w.
+
+NPAR TESTS
+       /BINOMIAL(0.5) = x (10, 20)
+       .
 EOF
 if [ $? -ne 0 ] ; then no_result ; fi
 
@@ -300,6 +330,24 @@ P == 0.5; N1/N2 == 1
 | |Group2#    2.00|10|          .500|          |                     |
 | |Total #        |20|          1.00|          |                     |
 +-+------#--------+--+--------------+----------+---------------------+
+P == 0.5; N1/N2 == 1 Cutpoint
+10.1 NPAR TESTS.  Binomial Test
++-+------#--------+--+--------------+----------+---------------------+
+| |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
++-+------#--------+--+--------------+----------+---------------------+
+|x|Group1#   <= 10|10|          .385|      .500|                 .327|
+| |Group2#        |16|          .615|          |                     |
+| |Total #        |26|          1.00|          |                     |
++-+------#--------+--+--------------+----------+---------------------+
+P == 0.5; N1/N2 == 1 Named values
+11.1 NPAR TESTS.  Binomial Test
++-+------#--------+--+--------------+----------+---------------------+
+| |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
++-+------#--------+--+--------------+----------+---------------------+
+|x|Group1#   10.00|10|          .435|      .500|                 .678|
+| |Group2#   20.00|13|          .565|          |                     |
+| |Total #        |23|          1.00|          |                     |
++-+------#--------+--+--------------+----------+---------------------+
 EOF
 if [ $? -ne 0 ] ; then fail ; fi