#include <math.h>
#include "data/casereader.h"
+#include "data/casewriter.h"
#include "data/dataset.h"
#include "data/dictionary.h"
#include "data/mrset.h"
+#include "data/subcase.h"
#include "data/value-labels.h"
#include "language/command.h"
#include "language/lexer/format-parser.h"
#include "libpspp/message.h"
#include "libpspp/string-array.h"
#include "math/moments.h"
+#include "math/percentiles.h"
+#include "math/sort.h"
#include "output/pivot-table.h"
#include "gl/minmax.h"
/* MEAN, SEMEAN, STDDEV, SUM, VARIANCE, *.SUM. */
struct moments1 *moments;
- /* XXX percentiles, median, mode, multiple response */
+ struct
+ {
+ struct casewriter *writer;
+ double mvalid;
+ double median;
+ };
+
+ /* XXX percentiles, mode, multiple response */
};
static void
case CTSF_LAYERPCT_TOTALN:
case CTSF_LAYERROWPCT_TOTALN:
case CTSF_LAYERCOLPCT_TOTALN:
+ case CTSF_MISSING:
case CSTF_TOTALN:
case CTSF_ETOTALN:
case CTSF_VALIDN:
break;
case CTSF_MEDIAN:
- case CTSF_MISSING:
+ {
+ struct caseproto *proto = caseproto_create ();
+ proto = caseproto_add_width (proto, 0);
+ proto = caseproto_add_width (proto, 0);
+
+ struct subcase ordering;
+ subcase_init (&ordering, 0, 0, SC_ASCEND);
+ s->writer = sort_create_writer (&ordering, proto);
+ subcase_uninit (&ordering);
+ caseproto_unref (proto);
+
+ s->mvalid = 0;
+ s->median = SYSMIS;
+ }
+ break;
+
case CTSF_MODE:
case CTSF_PTILE:
NOT_REACHED ();
case CTSF_LAYERPCT_TOTALN:
case CTSF_LAYERROWPCT_TOTALN:
case CTSF_LAYERCOLPCT_TOTALN:
+ case CTSF_MISSING:
case CSTF_TOTALN:
case CTSF_ETOTALN:
case CTSF_VALIDN:
break;
case CTSF_MEDIAN:
- case CTSF_MISSING:
+ casewriter_destroy (s->writer);
+ break;
+
case CTSF_MODE:
case CTSF_PTILE:
NOT_REACHED ();
case CTSF_LAYERPCT_TOTALN:
case CTSF_LAYERROWPCT_TOTALN:
case CTSF_LAYERCOLPCT_TOTALN:
+ case CTSF_MISSING:
case CSTF_TOTALN:
case CTSF_ETOTALN:
case CTSF_VALIDN:
break;
case CTSF_MEDIAN:
- case CTSF_MISSING:
+ if (var_is_value_missing (var, value))
+ {
+ s->mvalid += weight;
+
+ struct ccase *c = case_create (casewriter_get_proto (s->writer));
+ *case_num_rw_idx (c, 0) = value->f;
+ *case_num_rw_idx (c, 1) = weight;
+ casewriter_write (s->writer, c);
+ }
+ break;
+
case CTSF_MODE:
case CTSF_PTILE:
NOT_REACHED ();
case CTSF_LAYERCOLPCT_TOTALN:
NOT_REACHED ();
+ case CTSF_MISSING:
+ return s->missing;
+
case CSTF_TOTALN:
case CTSF_ETOTALN:
return s->valid + s->missing;
NOT_REACHED ();
case CTSF_MEDIAN:
- case CTSF_MISSING:
+ if (s->writer)
+ {
+ struct casereader *reader = casewriter_make_reader (s->writer);
+ s->writer = NULL;
+
+ struct percentile *median = percentile_create (0.5, s->mvalid);
+ struct order_stats *os = &median->parent;
+ order_stats_accumulate_idx (&os, 1, reader, 1, 0);
+ s->median = percentile_calculate (median, PC_HAVERAGE);
+ statistic_destroy (&median->parent.parent);
+ }
+ return s->median;
+
case CTSF_MODE:
case CTSF_PTILE:
NOT_REACHED ();