commit
message
[RANK.AVG] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-30 12:20:25
stats
8 file(s) changed,
132 insertions(+),
8 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 66067ae..9effb9c 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -2090,6 +2090,17 @@
6 @returns {number}
7 @constructor
8 ```
9+
10+### AVG
11+
12+```
13+ Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top. If more than one value exists in the same data-set, the average range of the values will be returned.
14+@param value - Value to find the rank of.
15+@param data - Values or range of the data-set.
16+@param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to 0.
17+@returns {number}
18+@constructor
19+```
20 ## Text
21
22
23diff --git a/TODO.md b/TODO.md
24index a1bf6b5..9cc3342 100644
25--- a/TODO.md
26+++ b/TODO.md
27@@ -65,7 +65,6 @@ Many of these formulas can be written by allowing the Sheet and Parser to return
28 * HYPGEOMDIST
29 * LOGINV
30 * LOGNORMDIST
31-* RANK.AVG
32 * RANK.EQ
33 * T.INV
34 * T.INV.2T
35diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
36index 90b6b95..6b9608d 100644
37--- a/dist/Formulas/AllFormulas.js
38+++ b/dist/Formulas/AllFormulas.js
39@@ -194,6 +194,7 @@ exports.STEYX = Statistical_1.STEYX;
40 exports.PROB = Statistical_1.PROB;
41 exports.MODE = Statistical_1.MODE;
42 exports.RANK = Statistical_1.RANK;
43+exports.RANK$AVG = Statistical_1.RANK$AVG;
44 var Text_1 = require("./Text");
45 exports.ARABIC = Text_1.ARABIC;
46 exports.CHAR = Text_1.CHAR;
47@@ -238,6 +239,7 @@ var __COMPLEX = {
48 "POISSON.DIST": Statistical_1.POISSON,
49 "PERCENTRANK.INC": Statistical_1.PERCENTRANK,
50 "PERCENTRANK.EXC": Statistical_1.PERCENTRANK$EXC,
51- "ERROR.TYPE": Info_1.ERRORTYPE
52+ "ERROR.TYPE": Info_1.ERRORTYPE,
53+ "RANK.AVG": Statistical_1.RANK$AVG
54 };
55 exports.__COMPLEX = __COMPLEX;
56diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
57index b8b1cef..ec2d588 100644
58--- a/dist/Formulas/Statistical.js
59+++ b/dist/Formulas/Statistical.js
60@@ -1889,3 +1889,41 @@ var RANK = function (value, data, isAscending) {
61 return range.indexOf(value) + 1;
62 };
63 exports.RANK = RANK;
64+/**
65+ * Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top. If
66+ * more than one value exists in the same data-set, the average range of the values will be returned.
67+ * @param value - Value to find the rank of.
68+ * @param data - Values or range of the data-set.
69+ * @param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to
70+ * 0.
71+ * @returns {number}
72+ * @constructor
73+ */
74+var RANK$AVG = function (value, data, isAscending) {
75+ ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 2, 3, "RANK.AVG");
76+ value = TypeConverter_1.TypeConverter.firstValueAsNumber(value);
77+ var range = Filter_1.Filter.flattenAndThrow(data).map(TypeConverter_1.TypeConverter.valueToNumber);
78+ function _countIn(range, value) {
79+ var result = 0;
80+ for (var i = 0; i < range.length; i++) {
81+ if (range[i] === value) {
82+ result++;
83+ }
84+ }
85+ return result;
86+ }
87+ isAscending = (typeof isAscending === 'undefined') ? false : isAscending;
88+ var sort = (isAscending) ? function (a, b) {
89+ return a - b;
90+ } : function (a, b) {
91+ return b - a;
92+ };
93+ range = range.sort(sort);
94+ var rangeIndex = range.indexOf(value);
95+ if (rangeIndex === -1) {
96+ throw new Errors_1.NAError("RANK.AVG can't produce a result because parameter 1 is not in the dataset.");
97+ }
98+ var count = _countIn(range, value);
99+ return (count > 1) ? (2 * rangeIndex + count + 1) / 2 : rangeIndex + 1;
100+};
101+exports.RANK$AVG = RANK$AVG;
102diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
103index fbffeff..9337b08 100644
104--- a/src/Formulas/AllFormulas.ts
105+++ b/src/Formulas/AllFormulas.ts
106@@ -199,7 +199,8 @@ import {
107 STEYX,
108 PROB,
109 MODE,
110- RANK
111+ RANK,
112+ RANK$AVG
113 } from "./Statistical";
114 import {
115 ARABIC,
116@@ -248,7 +249,8 @@ var __COMPLEX = {
117 "POISSON.DIST": POISSON,
118 "PERCENTRANK.INC": PERCENTRANK,
119 "PERCENTRANK.EXC": PERCENTRANK$EXC,
120- "ERROR.TYPE": ERRORTYPE
121+ "ERROR.TYPE": ERRORTYPE,
122+ "RANK.AVG": RANK$AVG
123 };
124
125 export {
126@@ -473,5 +475,6 @@ export {
127 STEYX,
128 PROB,
129 MODE,
130- RANK
131+ RANK,
132+ RANK$AVG
133 }
134\ No newline at end of file
135diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
136index 5b12993..6a55a42 100644
137--- a/src/Formulas/Statistical.ts
138+++ b/src/Formulas/Statistical.ts
139@@ -1870,6 +1870,47 @@ var RANK = function (value, data, isAscending?) {
140 };
141
142
143+/**
144+ * Returns the position of a given entry in the entire list, measured either from top to bottom or bottom to top. If
145+ * more than one value exists in the same data-set, the average range of the values will be returned.
146+ * @param value - Value to find the rank of.
147+ * @param data - Values or range of the data-set.
148+ * @param isAscending - [OPTIONAL] The type of rank: 0 to rank from the highest, 1 to rank from the lowest. Defaults to
149+ * 0.
150+ * @returns {number}
151+ * @constructor
152+ */
153+var RANK$AVG = function (value, data, isAscending?) {
154+ ArgsChecker.checkLengthWithin(arguments, 2, 3, "RANK.AVG");
155+ value = TypeConverter.firstValueAsNumber(value);
156+ var range = Filter.flattenAndThrow(data).map(TypeConverter.valueToNumber)
157+
158+ function _countIn(range, value) {
159+ var result = 0;
160+ for (var i = 0; i < range.length; i++) {
161+ if (range[i] === value) {
162+ result++;
163+ }
164+ }
165+ return result;
166+ }
167+
168+ isAscending = (typeof isAscending === 'undefined') ? false : isAscending;
169+ var sort = (isAscending) ? function (a, b) {
170+ return a - b;
171+ } : function (a, b) {
172+ return b - a;
173+ };
174+ range = range.sort(sort);
175+ var rangeIndex = range.indexOf(value);
176+ if (rangeIndex === -1) {
177+ throw new NAError("RANK.AVG can't produce a result because parameter 1 is not in the dataset.");
178+ }
179+ var count = _countIn(range, value);
180+ return (count > 1) ? (2 * rangeIndex + count + 1) / 2 : rangeIndex + 1;
181+};
182+
183+
184 export {
185 AVERAGE,
186 AVERAGEA,
187@@ -1928,5 +1969,6 @@ export {
188 STEYX,
189 PROB,
190 MODE,
191- RANK
192+ RANK,
193+ RANK$AVG
194 }
195\ No newline at end of file
196diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
197index d11c21a..b0e1836 100644
198--- a/tests/Formulas/StatisticalTest.ts
199+++ b/tests/Formulas/StatisticalTest.ts
200@@ -56,7 +56,8 @@ import {
201 STEYX,
202 PROB,
203 MODE,
204- RANK
205+ RANK,
206+ RANK$AVG
207 } from "../../src/Formulas/Statistical";
208 import * as ERRORS from "../../src/Errors";
209 import {
210@@ -1133,6 +1134,8 @@ test("MODE", function() {
211
212 test("RANK", function() {
213 assertEquals(RANK(2, [1, 2, 3, 4, 5, 6, 7, 8, 9], true), 2);
214+ assertEquals(RANK(3, [1, 3, 4, 5, 6, 7, 8, 9]), 7);
215+ assertEquals(RANK(3, [1, 3, 4, 5, 6, 7, 8, 9], true), 2);
216 assertEquals(RANK(2, [7, 1, 2, 4, 100, 8, 9], true), 2);
217 catchAndAssertEquals(function() {
218 RANK(44, [7, 1]);
219@@ -1143,4 +1146,23 @@ test("RANK", function() {
220 catchAndAssertEquals(function() {
221 RANK.apply(this, [44, [7, 1], true, false]);
222 }, ERRORS.NA_ERROR);
223+});
224+
225+test("RANK.AVG", function() {
226+ assertEquals(RANK$AVG(2, [1, 2, 2, 3, 4, 5, 6, 7, 8, 9], true), 2.5);
227+ assertEquals(RANK$AVG(2, [1, 2, 2, 3, 4, 5, 6, 7, 8, 9]), 8.5);
228+ assertEquals(RANK$AVG(2, [2]), 1);
229+ assertEquals(RANK$AVG(2, [1, 2, 3, 4, 5, 6, 7, 8, 9], true), 2);
230+ assertEquals(RANK$AVG(3, [1, 3, 4, 5, 6, 7, 8, 9]), 7);
231+ assertEquals(RANK$AVG(3, [1, 3, 4, 5, 6, 7, 8, 9], true), 2);
232+ assertEquals(RANK$AVG(2, [7, 1, 2, 4, 100, 8, 9], true), 2);
233+ catchAndAssertEquals(function() {
234+ RANK$AVG(44, [7, 1]);
235+ }, ERRORS.NA_ERROR);
236+ catchAndAssertEquals(function() {
237+ RANK$AVG.apply(this, [44]);
238+ }, ERRORS.NA_ERROR);
239+ catchAndAssertEquals(function() {
240+ RANK$AVG.apply(this, [44, [7, 1], true, false]);
241+ }, ERRORS.NA_ERROR);
242 });
243\ No newline at end of file
244diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
245index cda030d..99cce03 100644
246--- a/tests/SheetFormulaTest.ts
247+++ b/tests/SheetFormulaTest.ts
248@@ -934,6 +934,11 @@ test("Sheet RANK", function(){
249 assertFormulaEquals('=RANK([2], [1, 2, 3, 4, 5, 6, 7, 8, 9], true)', 2);
250 });
251
252+test("Sheet RANK.AVG", function(){
253+ assertFormulaEquals('=RANK.AVG([2], [1, 2, 3, 4, 5, 6, 7, 8, 9], true)', 2);
254+});
255+
256+
257 test("Sheet *", function(){
258 assertFormulaEquals('= 10 * 10', 100);
259 assertFormulaEquals('= 10 * 0', 0);