spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
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);