Fixed misleading results in the Kruskal-Wallis test
[pspp] / src / language / stats / kruskal-wallis.c
index ae6fffe205118decea725ed1badc9f6e17be7034..6d54bae78208d74b98db28007cf831d3cbc37c94 100644 (file)
@@ -1,5 +1,5 @@
 /* Pspp - a program for statistical analysis.
-   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2010, 2011, 2022 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
 #define N_(msgid) msgid
 #define _(msgid) gettext (msgid)
 
-/* Returns true iff the independent variable lies in the range [nst->val1, nst->val2] */
+/* Returns true iff the independent variable lies between nst->val1 and  nst->val2 */
 static bool
 include_func (const struct ccase *c, void *aux)
 {
   const struct n_sample_test *nst = aux;
 
-  if (0 < value_compare_3way (&nst->val1, case_data (c, nst->indep_var), var_get_width (nst->indep_var)))
+  const union value *smaller = 0;
+  const union value *larger = 0;
+  int x = value_compare_3way (&nst->val1, &nst->val2, var_get_width (nst->indep_var));
+   if (x < 0)
+    {
+      smaller = &nst->val1;
+      larger = &nst->val2;
+    }
+  else
+    {
+      smaller = &nst->val2;
+      larger = &nst->val1;
+    }
+
+  if (0 < value_compare_3way (smaller, case_data (c, nst->indep_var),
+                              var_get_width (nst->indep_var)))
     return false;
 
-  if (0 > value_compare_3way (&nst->val2, case_data (c, nst->indep_var), var_get_width (nst->indep_var)))
+  if (0 > value_compare_3way (larger, case_data (c, nst->indep_var),
+                              var_get_width (nst->indep_var)))
     return false;
 
   return true;
@@ -137,7 +153,7 @@ kruskal_wallis_execute (const struct dataset *ds,
 
   int total_n_groups = 0.0;
 
-  struct kw *kw = xcalloc (nst->n_vars, sizeof *kw);
+  struct kw *kw = XCALLOC (nst->n_vars,  struct kw);
 
   /* If the independent variable is missing, then we ignore the case */
   input = casereader_create_filter_missing (input,
@@ -183,7 +199,7 @@ kruskal_wallis_execute (const struct dataset *ds,
          const size_t group_var_width = var_get_width (nst->indep_var);
          struct rank_entry *rank = find_rank_entry (&kw[i].map, group, group_var_width);
 
-         if ( NULL == rank)
+         if (NULL == rank)
            {
              rank = xzalloc (sizeof *rank);
              value_clone (&rank->group, group, group_var_width);
@@ -192,7 +208,7 @@ kruskal_wallis_execute (const struct dataset *ds,
                           value_hash (&rank->group, group_var_width, 0));
            }
 
-         rank->sum_of_ranks += case_data_idx (c, rank_idx)->f;
+         rank->sum_of_ranks += case_num_idx (c, rank_idx);
          rank->n += dict_get_case_weight (dict, c, &warn);
 
          /* If this assertion fires, then either the data wasn't sorted or some other
@@ -214,7 +230,7 @@ kruskal_wallis_execute (const struct dataset *ds,
 
            total_n_groups ++;
          }
-       kw[i].h *= 12 / (n * ( n + 1));
+       kw[i].h *= 12 / (n * (n + 1));
        kw[i].h -= 3 * (n + 1) ;
 
        kw[i].h /= 1 - tiebreaker/ (pow3 (n) - n);