commit
message
[MODE] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-30 11:48:02
stats
8 file(s) changed,
103 insertions(+),
6 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Statistical.js
src/Formulas/AllFormulas.ts
src/Formulas/Statistical.ts
tests/Formulas/StatisticalTest.ts
tests/SheetFormulaTest.ts
1diff --git a/DOCS.md b/DOCS.md
2index 4a20aed..a7842f6 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -2070,6 +2070,15 @@
6 @returns {number}
7 @constructor
8 ```
9+
10+### MODE
11+
12+```
13+ Returns the most commonly occurring value in a range.
14+@param values - Range(s) or values to consider.
15+@returns {number}
16+@constructor
17+```
18 ## Text
19
20
21diff --git a/TODO.md b/TODO.md
22index 7078dd2..85605ed 100644
23--- a/TODO.md
24+++ b/TODO.md
25@@ -65,7 +65,6 @@ Many of these formulas can be written by allowing the Sheet and Parser to return
26 * HYPGEOMDIST
27 * LOGINV
28 * LOGNORMDIST
29-* MODE
30 * RANK
31 * RANK.AVG
32 * RANK.EQ
33diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
34index 5acd2b4..232bd48 100644
35--- a/dist/Formulas/AllFormulas.js
36+++ b/dist/Formulas/AllFormulas.js
37@@ -192,6 +192,7 @@ exports.RSQ = Statistical_1.RSQ;
38 exports.SKEW = Statistical_1.SKEW;
39 exports.STEYX = Statistical_1.STEYX;
40 exports.PROB = Statistical_1.PROB;
41+exports.MODE = Statistical_1.MODE;
42 var Text_1 = require("./Text");
43 exports.ARABIC = Text_1.ARABIC;
44 exports.CHAR = Text_1.CHAR;
45diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
46index 046b0f9..651d5a2 100644
47--- a/dist/Formulas/Statistical.js
48+++ b/dist/Formulas/Statistical.js
49@@ -1827,3 +1827,38 @@ var PROB = function (range, probability, start, end) {
50 return result;
51 };
52 exports.PROB = PROB;
53+/**
54+ * Returns the most commonly occurring value in a range.
55+ * @param values - Range(s) or values to consider.
56+ * @returns {number}
57+ * @constructor
58+ */
59+var MODE = function () {
60+ var values = [];
61+ for (var _i = 0; _i < arguments.length; _i++) {
62+ values[_i] = arguments[_i];
63+ }
64+ ArgsChecker_1.ArgsChecker.checkAtLeastLength(arguments, 1, "MODE");
65+ var range = Filter_1.Filter.flattenAndThrow(values).map(TypeConverter_1.TypeConverter.valueToNumber);
66+ var n = range.length;
67+ var count = {};
68+ var maxItems = [];
69+ var max = 0;
70+ var currentItem;
71+ for (var i = 0; i < n; i++) {
72+ currentItem = range[i];
73+ count[currentItem] = count[currentItem] ? count[currentItem] + 1 : 1;
74+ if (count[currentItem] > max) {
75+ max = count[currentItem];
76+ maxItems = [];
77+ }
78+ if (count[currentItem] === max) {
79+ maxItems[maxItems.length] = currentItem;
80+ }
81+ }
82+ if (max === 1 && range.length !== 1) {
83+ throw new Errors_1.NAError("MODE cannot produce a result because no values occur more than once.");
84+ }
85+ return maxItems[0];
86+};
87+exports.MODE = MODE;
88diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
89index 1c85403..2a033c8 100644
90--- a/src/Formulas/AllFormulas.ts
91+++ b/src/Formulas/AllFormulas.ts
92@@ -197,7 +197,8 @@ import {
93 RSQ,
94 SKEW,
95 STEYX,
96- PROB
97+ PROB,
98+ MODE
99 } from "./Statistical";
100 import {
101 ARABIC,
102@@ -469,5 +470,6 @@ export {
103 RSQ,
104 SKEW,
105 STEYX,
106- PROB
107+ PROB,
108+ MODE
109 }
110\ No newline at end of file
111diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
112index 6db312c..6abae9b 100644
113--- a/src/Formulas/Statistical.ts
114+++ b/src/Formulas/Statistical.ts
115@@ -1810,6 +1810,38 @@ var PROB = function (range, probability, start, end?) {
116 };
117
118
119+/**
120+ * Returns the most commonly occurring value in a range.
121+ * @param values - Range(s) or values to consider.
122+ * @returns {number}
123+ * @constructor
124+ */
125+var MODE = function (...values) {
126+ ArgsChecker.checkAtLeastLength(arguments, 1, "MODE");
127+ var range = Filter.flattenAndThrow(values).map(TypeConverter.valueToNumber);
128+ var n = range.length;
129+ var count = {};
130+ var maxItems = [];
131+ var max = 0;
132+ var currentItem;
133+ for (var i = 0; i < n; i++) {
134+ currentItem = range[i];
135+ count[currentItem] = count[currentItem] ? count[currentItem] + 1 : 1;
136+ if (count[currentItem] > max) {
137+ max = count[currentItem];
138+ maxItems = [];
139+ }
140+ if (count[currentItem] === max) {
141+ maxItems[maxItems.length] = currentItem;
142+ }
143+ }
144+ if (max === 1 && range.length !== 1) {
145+ throw new NAError("MODE cannot produce a result because no values occur more than once.");
146+ }
147+ return maxItems[0];
148+};
149+
150+
151 export {
152 AVERAGE,
153 AVERAGEA,
154@@ -1866,5 +1898,6 @@ export {
155 RSQ,
156 SKEW,
157 STEYX,
158- PROB
159+ PROB,
160+ MODE
161 }
162\ No newline at end of file
163diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
164index 700b319..1b446a5 100644
165--- a/tests/Formulas/StatisticalTest.ts
166+++ b/tests/Formulas/StatisticalTest.ts
167@@ -54,7 +54,8 @@ import {
168 RSQ,
169 SKEW,
170 STEYX,
171- PROB
172+ PROB,
173+ MODE
174 } from "../../src/Formulas/Statistical";
175 import * as ERRORS from "../../src/Errors";
176 import {
177@@ -1113,4 +1114,18 @@ test("PROB", function() {
178 catchAndAssertEquals(function() {
179 PROB.apply(this, [[1, 2, 3, 4], [0.25, 0.25, 0.25], 10, 10, 10]);
180 }, ERRORS.NA_ERROR);
181+});
182+
183+test("MODE", function() {
184+ assertEquals(MODE(1, 6, 7, 7, 8), 7);
185+ assertEquals(MODE(1, 6, 6, 7, 7, 8), 6);
186+ assertEquals(MODE(1, 6, 6, 7, 8), 6);
187+ assertEquals(MODE(1, 6, 6, 7, "10"), 6);
188+ assertEquals(MODE(1), 1);
189+ catchAndAssertEquals(function() {
190+ MODE(1, 2, 8);
191+ }, ERRORS.NA_ERROR);
192+ catchAndAssertEquals(function() {
193+ MODE();
194+ }, ERRORS.NA_ERROR);
195 });
196\ No newline at end of file
197diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
198index afc6d67..9c5419f 100644
199--- a/tests/SheetFormulaTest.ts
200+++ b/tests/SheetFormulaTest.ts
201@@ -926,6 +926,10 @@ test("Sheet PROB", function(){
202 assertFormulaEquals('=PROB([1, 2, 3, 4], [0.25, 0.25, 0.25, 0.25], 3)', 0.25);
203 });
204
205+test("Sheet MODE", function(){
206+ assertFormulaEquals('=MODE(1, 6, 7, 7, 8)', 7);
207+});
208+
209 test("Sheet *", function(){
210 assertFormulaEquals('= 10 * 10', 100);
211 assertFormulaEquals('= 10 * 0', 0);