ctables: Support mode (untested).
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 30 Jan 2022 00:57:26 +0000 (16:57 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 2 Apr 2022 01:48:55 +0000 (18:48 -0700)
src/language/stats/ctables.c

index 5f9d2584c809649d527cf0bd59a0f879cd38eefb..17032c8c8e90db6e77a4038cb00354a040cbb72f 100644 (file)
@@ -35,6 +35,7 @@
 #include "libpspp/hmap.h"
 #include "libpspp/message.h"
 #include "libpspp/string-array.h"
+#include "math/mode.h"
 #include "math/moments.h"
 #include "math/percentiles.h"
 #include "math/sort.h"
@@ -1685,11 +1686,12 @@ union ctables_summary
     /* MEAN, SEMEAN, STDDEV, SUM, VARIANCE, *.SUM. */
     struct moments1 *moments;
 
+    /* MEDIAN, MODE. */
     struct
       {
         struct casewriter *writer;
-        double mvalid;
-        double median;
+        double ovalid;
+        double ovalue;
       };
 
     /* XXX percentiles, mode, multiple response */
@@ -1754,6 +1756,7 @@ ctables_summary_init (union ctables_summary *s,
       break;
 
     case CTSF_MEDIAN:
+    case CTSF_MODE:
       {
         struct caseproto *proto = caseproto_create ();
         proto = caseproto_add_width (proto, 0);
@@ -1765,12 +1768,11 @@ ctables_summary_init (union ctables_summary *s,
         subcase_uninit (&ordering);
         caseproto_unref (proto);
 
-        s->mvalid = 0;
-        s->median = SYSMIS;
+        s->ovalid = 0;
+        s->ovalue = SYSMIS;
       }
       break;
 
-    case CTSF_MODE:
     case CTSF_PTILE:
       NOT_REACHED ();
 
@@ -1857,10 +1859,10 @@ ctables_summary_uninit (union ctables_summary *s,
       break;
 
     case CTSF_MEDIAN:
+    case CTSF_MODE:
       casewriter_destroy (s->writer);
       break;
 
-    case CTSF_MODE:
     case CTSF_PTILE:
       NOT_REACHED ();
 
@@ -1962,9 +1964,10 @@ ctables_summary_add (union ctables_summary *s,
       break;
 
     case CTSF_MEDIAN:
+    case CTSF_MODE:
       if (var_is_value_missing (var, value))
         {
-          s->mvalid += weight;
+          s->ovalid += weight;
 
           struct ccase *c = case_create (casewriter_get_proto (s->writer));
           *case_num_rw_idx (c, 0) = value->f;
@@ -1973,7 +1976,6 @@ ctables_summary_add (union ctables_summary *s,
         }
       break;
 
-    case CTSF_MODE:
     case CTSF_PTILE:
       NOT_REACHED ();
 
@@ -2121,15 +2123,28 @@ ctables_summary_value (const struct ctables_cell *cell,
           struct casereader *reader = casewriter_make_reader (s->writer);
           s->writer = NULL;
 
-          struct percentile *median = percentile_create (0.5, s->mvalid);
+          struct percentile *median = percentile_create (0.5, s->ovalid);
           struct order_stats *os = &median->parent;
           order_stats_accumulate_idx (&os, 1, reader, 1, 0);
-          s->median = percentile_calculate (median, PC_HAVERAGE);
+          s->ovalue = percentile_calculate (median, PC_HAVERAGE);
           statistic_destroy (&median->parent.parent);
         }
-      return s->median;
+      return s->ovalue;
 
     case CTSF_MODE:
+      if (s->writer)
+        {
+          struct casereader *reader = casewriter_make_reader (s->writer);
+          s->writer = NULL;
+
+          struct mode *mode = mode_create ();
+          struct order_stats *os = &mode->parent;
+          order_stats_accumulate_idx (&os, 1, reader, 1, 0);
+          s->ovalue = mode->mode;
+          statistic_destroy (&mode->parent.parent);
+        }
+      return s->ovalue;
+
     case CTSF_PTILE:
       NOT_REACHED ();