commit
message
[FREQUENCY] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-06-19 01:41:34
stats
9 file(s) changed,
172 insertions(+),
5 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Range.js
src/Formulas/AllFormulas.ts
src/Formulas/Range.ts
tests/Formulas/RangeTest.ts
tests/SheetFormulaTest.ts
tests/Utils/Asserts.ts
1diff --git a/DOCS.md b/DOCS.md
2index e0ac0a2..6a63693 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -1234,6 +1234,18 @@
6 @returns {number}
7 @constructor
8 ```
9+## Range
10+
11+
12+### FREQUENCY
13+
14+```
15+ Calculates the frequency distribution of a range into specified classes or "bins".
16+@param range - to get frequency for.
17+@param bins - or classes.
18+@returns {Array<number>}
19+@constructor
20+```
21 ## Statistical
22
23
24diff --git a/TODO.md b/TODO.md
25index b2bbc48..c8fb1fb 100644
26--- a/TODO.md
27+++ b/TODO.md
28@@ -130,7 +130,6 @@ For example 64 tbs to a qt.
29 * TEXT
30 * UPPER
31 * VALUE
32-* FREQUENCY
33 * GROWTH
34 * LINEST
35 * LOGEST
36diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
37index 41b3da6..8e019cd 100644
38--- a/dist/Formulas/AllFormulas.js
39+++ b/dist/Formulas/AllFormulas.js
40@@ -73,6 +73,8 @@ exports.UPLUS = Math_1.UPLUS;
41 exports.UMINUS = Math_1.UMINUS;
42 exports.MROUND = Math_1.MROUND;
43 exports.FACTDOUBLE = Math_1.FACTDOUBLE;
44+var Range_1 = require("./Range");
45+exports.FREQUENCY = Range_1.FREQUENCY;
46 var Info_1 = require("./Info");
47 exports.NA = Info_1.NA;
48 exports.ISTEXT = Info_1.ISTEXT;
49diff --git a/dist/Formulas/Range.js b/dist/Formulas/Range.js
50new file mode 100644
51index 0000000..493a0b1
52--- /dev/null
53+++ b/dist/Formulas/Range.js
54@@ -0,0 +1,56 @@
55+"use strict";
56+exports.__esModule = true;
57+var ArgsChecker_1 = require("../Utilities/ArgsChecker");
58+var Filter_1 = require("../Utilities/Filter");
59+var TypeConverter_1 = require("../Utilities/TypeConverter");
60+/**
61+ * Calculates the frequency distribution of a range into specified classes or "bins".
62+ * @param range - to get frequency for.
63+ * @param bins - or classes.
64+ * @returns {Array<number>}
65+ * @constructor
66+ */
67+var FREQUENCY = function (range, bins) {
68+ ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "FREQUENCY");
69+ if (!Array.isArray(bins)) {
70+ bins = [bins];
71+ }
72+ if (!Array.isArray(range)) {
73+ range = [range];
74+ }
75+ bins = Filter_1.Filter.flattenAndThrow(bins).map(function (value) {
76+ return TypeConverter_1.TypeConverter.firstValueAsNumber(value);
77+ }).sort(function (a, b) {
78+ return a - b;
79+ });
80+ range = Filter_1.Filter.flattenAndThrow(range).map(function (value) {
81+ return TypeConverter_1.TypeConverter.firstValueAsNumber(value);
82+ }).sort(function (a, b) {
83+ return a - b;
84+ });
85+ var n = range.length;
86+ var b = bins.length;
87+ var r = [];
88+ for (var i = 0; i <= b; i++) {
89+ r[i] = 0;
90+ for (var j = 0; j < n; j++) {
91+ if (i === 0) {
92+ if (range[j] <= bins[0]) {
93+ r[0] += 1;
94+ }
95+ }
96+ else if (i < b) {
97+ if (range[j] > bins[i - 1] && range[j] <= bins[i]) {
98+ r[i] += 1;
99+ }
100+ }
101+ else if (i === b) {
102+ if (range[j] > bins[b - 1]) {
103+ r[b] += 1;
104+ }
105+ }
106+ }
107+ }
108+ return r;
109+};
110+exports.FREQUENCY = FREQUENCY;
111diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
112index 8402b80..6946d58 100644
113--- a/src/Formulas/AllFormulas.ts
114+++ b/src/Formulas/AllFormulas.ts
115@@ -72,6 +72,9 @@ import {
116 MROUND,
117 FACTDOUBLE
118 } from "./Math";
119+import {
120+ FREQUENCY
121+} from "./Range";
122 import {
123 NA,
124 ISTEXT,
125@@ -339,5 +342,6 @@ export {
126 ISNUMBER,
127 ISNONTEXT,
128 MROUND,
129- FACTDOUBLE
130+ FACTDOUBLE,
131+ FREQUENCY
132 }
133\ No newline at end of file
134diff --git a/src/Formulas/Range.ts b/src/Formulas/Range.ts
135new file mode 100644
136index 0000000..599103d
137--- /dev/null
138+++ b/src/Formulas/Range.ts
139@@ -0,0 +1,60 @@
140+import {
141+ ArgsChecker
142+} from "../Utilities/ArgsChecker";
143+import {Filter} from "../Utilities/Filter";
144+import {TypeConverter} from "../Utilities/TypeConverter";
145+
146+
147+/**
148+ * Calculates the frequency distribution of a range into specified classes or "bins".
149+ * @param range - to get frequency for.
150+ * @param bins - or classes.
151+ * @returns {Array<number>}
152+ * @constructor
153+ */
154+var FREQUENCY = function (range, bins) : Array<number> {
155+ ArgsChecker.checkLength(arguments, 2, "FREQUENCY");
156+ if (!Array.isArray(bins)) {
157+ bins = [bins];
158+ }
159+ if (!Array.isArray(range)) {
160+ range = [range];
161+ }
162+ bins = Filter.flattenAndThrow(bins).map(function (value) {
163+ return TypeConverter.firstValueAsNumber(value);
164+ }).sort(function (a, b) {
165+ return a - b;
166+ });
167+ range = Filter.flattenAndThrow(range).map(function (value) {
168+ return TypeConverter.firstValueAsNumber(value);
169+ }).sort(function (a, b) {
170+ return a - b;
171+ });
172+
173+ var n = range.length;
174+ var b = bins.length;
175+ var r = [];
176+ for (var i = 0; i <= b; i++) {
177+ r[i] = 0;
178+ for (var j = 0; j < n; j++) {
179+ if (i === 0) {
180+ if (range[j] <= bins[0]) {
181+ r[0] += 1;
182+ }
183+ } else if (i < b) {
184+ if (range[j] > bins[i - 1] && range[j] <= bins[i]) {
185+ r[i] += 1;
186+ }
187+ } else if (i === b) {
188+ if (range[j] > bins[b - 1]) {
189+ r[b] += 1;
190+ }
191+ }
192+ }
193+ }
194+ return r;
195+};
196+
197+export {
198+ FREQUENCY
199+}
200\ No newline at end of file
201diff --git a/tests/Formulas/RangeTest.ts b/tests/Formulas/RangeTest.ts
202new file mode 100644
203index 0000000..d7604d3
204--- /dev/null
205+++ b/tests/Formulas/RangeTest.ts
206@@ -0,0 +1,28 @@
207+import {
208+ FREQUENCY
209+} from "../../src/Formulas/Range";
210+import {
211+ assertArrayEquals,
212+ catchAndAssertEquals,
213+ test
214+} from "../Utils/Asserts";
215+import * as ERRORS from "../../src/Errors";
216+
217+
218+
219+test("FREQUENCY", function(){
220+ assertArrayEquals(FREQUENCY([10, 2, 3, 44, 1, 2], 22), [5, 1]);
221+ assertArrayEquals(FREQUENCY([10, 2, 3, 44, 1, 2], [22]), [5, 1]);
222+ assertArrayEquals(FREQUENCY([10, [2, 3, 44, 1], 2], [22]), [5, 1]);
223+ assertArrayEquals(FREQUENCY([18, 30, 90, 91, 35, 27, 75, 28, 58], [25, 50, 75]), [1, 4, 2, 2]);
224+ assertArrayEquals(FREQUENCY([18, 30, 90, 91, 35, 27, 75, 28, 58], [50, 25, 75]), [1, 4, 2, 2]);
225+ catchAndAssertEquals(function() {
226+ FREQUENCY.apply(this, [10, 10, 10]);
227+ }, ERRORS.NA_ERROR);
228+ catchAndAssertEquals(function() {
229+ FREQUENCY.apply(this, [10]);
230+ }, ERRORS.NA_ERROR);
231+ catchAndAssertEquals(function() {
232+ FREQUENCY([10, 2, 3, 44, 1, [], 2], 22);
233+ }, ERRORS.REF_ERROR);
234+});
235\ No newline at end of file
236diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
237index fa889a5..fe0f265 100644
238--- a/tests/SheetFormulaTest.ts
239+++ b/tests/SheetFormulaTest.ts
240@@ -35,7 +35,7 @@ function assertFormulaResultsInType(formula: string, type: string) {
241 assertEquals(typeof cell.getValue(), type);
242 }
243
244-function testFormulaToArray(formula: string, expectation: any) {
245+function assertFormulaEqualsArray(formula: string, expectation: any) {
246 var sheet = new Sheet();
247 sheet.setCell("A1", formula);
248 var cell = sheet.getCell("A1");
249@@ -529,7 +529,7 @@ test("Sheet SINH", function(){
250 });
251
252 test("Sheet SPLIT", function(){
253- testFormulaToArray('=SPLIT("1,2,3", ",", TRUE)', [ '1', '2', '3' ]);
254+ assertFormulaEqualsArray('=SPLIT("1,2,3", ",", TRUE)', [ '1', '2', '3' ]);
255 });
256
257 test("Sheet SQRT", function(){
258@@ -679,6 +679,12 @@ test("Sheet FACTDOUBLE", function(){
259 assertFormulaEquals('=FACTDOUBLE(7)', 105);
260 });
261
262+
263+test("Sheet FREQUENCY", function(){
264+ assertFormulaEqualsArray('=FREQUENCY([10, 2, 3, 44, 1, 2], 22)', [5, 1]);
265+});
266+
267+
268 test("Sheet *", function(){
269 assertFormulaEquals('= 10 * 10', 100);
270 assertFormulaEquals('= 10 * 0', 0);
271diff --git a/tests/Utils/Asserts.ts b/tests/Utils/Asserts.ts
272index 2740d3e..3709262 100644
273--- a/tests/Utils/Asserts.ts
274+++ b/tests/Utils/Asserts.ts
275@@ -19,6 +19,7 @@ function assertArrayEquals(actual: Array<any>, expected: Array<any>, ) {
276 if (expected.length != actual.length) {
277 console.log("expected: ", expected, " actual:", actual);
278 console.trace();
279+ return;
280 }
281 for (var index in expected) {
282 if (expected[index] != actual[index]) {