commit
message
Starting to move functions from Math.ts to Statistical.ts
author
Ben Vogt <[email protected]>
date
2017-02-20 22:22:32
stats
3 file(s) changed,
263 insertions(+),
243 deletions(-)
files
src/RawFormulas/Math.ts
src/RawFormulas/RawFormulas.ts
src/RawFormulas/Statistical.ts
1diff --git a/src/RawFormulas/Math.ts b/src/RawFormulas/Math.ts
2index a4c735c..187a64c 100644
3--- a/src/RawFormulas/Math.ts
4+++ b/src/RawFormulas/Math.ts
5@@ -5,7 +5,9 @@ import {
6 Serializer,
7 TypeCaster
8 } from "./Utils";
9-import { CellError } from "../Errors";
10+import {
11+ CellError
12+} from "../Errors";
13 import * as ERRORS from "../Errors";
14
15 /**
16@@ -181,103 +183,6 @@ var ATANH = function (value?) : number {
17 return Math["atanh"](value);
18 };
19
20-
21-/**
22- * Returns the numerical average value in a dataset, ignoring text.
23- * @param values The values or ranges to consider when calculating the average value.
24- * @returns {number} the average value of this dataset.
25- * @constructor
26- */
27-var AVERAGE = function (...values) : number {
28- ArgsChecker.checkAtLeastLength(values, 1);
29- var result = 0;
30- var count = 0;
31- for (var i = 0; i < values.length; i++) {
32- if (values[i] instanceof Array) {
33- if (values[i].length === 0) {
34- throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
35- }
36- var filtered = Filter.filterOutStringValues(values[i]);
37- result = result + SUM.apply(this, filtered);
38- count += filtered.length;
39- } else {
40- result = result + TypeCaster.valueToNumber(values[i]);
41- count++;
42- }
43- }
44- return result / count;
45-};
46-
47-/**
48- * Calculates the average of the magnitudes of deviations of data from a dataset's mean.
49- * @param values The value(s) or range(s)
50- * @returns {number} average of the magnitudes of deviations of data from a dataset's mean
51- * @constructor
52- */
53-var AVEDEV = function (...values) {
54- ArgsChecker.checkAtLeastLength(values, 1);
55-
56- // Sort to array-values, and non-array-values
57- var arrayValues = [];
58- var nonArrayValues = [];
59- for (var i = 0; i < values.length; i++) {
60- var X = values[i];
61- if (X instanceof Array) {
62- if (X.length === 0) {
63- throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
64- }
65- arrayValues.push(X);
66- } else {
67- nonArrayValues.push(TypeCaster.valueToNumber(X));
68- }
69- }
70-
71- // Remove string values from array-values, but not from non-array-values, and concat.
72- var flatValues = Filter.filterOutStringValues(Filter.flatten(arrayValues)).map(function (value) {
73- return TypeCaster.valueToNumber(value);
74- }).concat(nonArrayValues);
75-
76- // Calculating mean
77- var result = 0;
78- var count = 0;
79- for (var i = 0; i < flatValues.length; i++) {
80- result = result + TypeCaster.valueToNumber(flatValues[i]);
81- count++;
82- }
83- var mean = result / count;
84-
85- for (var i = 0; i < flatValues.length; i++) {
86- flatValues[i] = ABS(TypeCaster.valueToNumber(flatValues[i]) - mean);
87- }
88- return SUM(flatValues) / flatValues.length;
89-};
90-
91-/**
92- * Returns the numerical average value in a dataset, coercing text values in ranges to 0 values.
93- * @param values value(s) or range(s) to consider when calculating the average value.
94- * @returns {number} the numerical average value in a dataset
95- * @constructor
96- */
97-var AVERAGEA = function (...values) {
98- ArgsChecker.checkAtLeastLength(values, 1);
99- var result = 0;
100- var count = 0;
101- for (var i = 0; i < values.length; i++) {
102- if (values[i] instanceof Array) {
103- if (values[i].length === 0) {
104- throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
105- }
106- var filtered = Filter.stringValuesToZeros(values[i]);
107- result = result + SUM.apply(this, filtered);
108- count += filtered.length;
109- } else {
110- result = result + TypeCaster.valueToNumber(values[i]);
111- count++;
112- }
113- }
114- return result / count;
115-};
116-
117 /**
118 * Rounds a number up to the nearest even integer.
119 * @param values[0] The value to round to the next greatest even number.
120@@ -332,51 +237,6 @@ var MAXA = function (...values) : number {
121 };
122
123
124-/**
125- * Returns the median value in a numeric dataset.
126- * @param values The value(s) or range(s) to consider when calculating the median value.
127- * @returns {number} the median value of the dataset
128- * @constructor
129- */
130-var MEDIAN = function (...values) : number {
131- ArgsChecker.checkAtLeastLength(values, 1);
132- var sortedArray = [];
133- values.forEach(function (currentValue) {
134- if (currentValue instanceof Array) {
135- if (currentValue.length === 0) {
136- throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
137- }
138- var filtered = Filter.filterOutStringValues(currentValue);
139- sortedArray = sortedArray.concat(filtered);
140- } else {
141- sortedArray.push(currentValue);
142- }
143- });
144- sortedArray = sortedArray.sort(function (a, b) {
145- var aN = TypeCaster.valueToNumber(a);
146- var bN = TypeCaster.valueToNumber(b);
147- return aN - bN;
148- });
149- if (sortedArray.length === 1) {
150- return TypeCaster.valueToNumber(sortedArray[0]);
151- }
152- if (sortedArray.length === 0) {
153- throw new CellError(ERRORS.NUM_ERROR, "MEDIAN has no valid input data.");
154- }
155- // even number of values
156- if (sortedArray.length % 2 === 0) {
157- if (sortedArray.length === 2) {
158- return AVERAGE(sortedArray[0], sortedArray[1]);
159- }
160- var top = sortedArray[sortedArray.length / 2];
161- var bottom = sortedArray[(sortedArray.length / 2) - 1];
162- return AVERAGE(top, bottom);
163- } else {
164- // odd number of values
165- return sortedArray[Math.round(sortedArray.length / 2) - 1];
166- }
167-};
168-
169 /**
170 * Returns the minimum value in a numeric dataset.
171 * @param values The value(s) or range(s) to consider when calculating the minimum value.
172@@ -1879,93 +1739,6 @@ var COMBIN = function (...values) : number {
173 return fact(n) / div;
174 };
175
176-
177-/**
178- * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
179- * will be ignored. CORREL is synonymous with PEARSON.
180- * @param values[0] data_y - The range representing the array or matrix of dependent data.
181- * @param values[1] data_x - The range representing the array or matrix of independent data.
182- * @returns {number} the Pearson product-moment correlation coefficient.
183- * @constructor
184- */
185-var CORREL = function (...values) : number {
186- function stdev(arr, flag) {
187- return Math.sqrt(variance(arr, flag));
188- }
189- function variance(arr, flag) {
190- if ((arr.length - (flag ? 1 : 0)) === 0) {
191- throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
192- }
193- return sumsqerr(arr) / (arr.length - (flag ? 1 : 0));
194- }
195- function sum(arr) {
196- var sum = 0;
197- var i = arr.length;
198- while (--i >= 0) {
199- sum += arr[i];
200- }
201- return sum;
202- }
203- function mean(arr) {
204- return sum(arr) / arr.length;
205- }
206- function sumsqerr(arr) {
207- var m = mean(arr);
208- var sum = 0;
209- var i = arr.length;
210- var tmp;
211- while (--i >= 0) {
212- tmp = arr[i] - m;
213- sum += tmp * tmp;
214- }
215- return sum;
216- }
217- function covariance(arr1, arr2) {
218- var u = mean(arr1);
219- var v = mean(arr2);
220- var arr1Len = arr1.length;
221- var sq_dev = new Array(arr1Len);
222- for (var i = 0; i < arr1Len; i++) {
223- sq_dev[i] = (arr1[i] - u) * (arr2[i] - v);
224- }
225- if ((arr1Len - 1) === 0) {
226- throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
227- }
228- return sum(sq_dev) / (arr1Len - 1);
229- }
230- ArgsChecker.checkLength(values, 2);
231- if (!Array.isArray(values[0])) {
232- values[0] = [values[0]];
233- }
234- if (!Array.isArray(values[1])) {
235- values[1] = [values[1]];
236- }
237- if (values[0].length !== values[1].length) {
238- throw new CellError(ERRORS.NA_ERROR, "CORREL has mismatched argument count " + values[0] + " vs " + values[1] + ".");
239- }
240- var arr1 = Filter.filterOutNonNumberValues(Filter.flattenAndThrow(values[0]));
241- var arr2 = Filter.filterOutNonNumberValues(Filter.flattenAndThrow(values[1]));
242- var stdevArr1 = stdev(arr1, 1);
243- var stdevArr2 = stdev(arr2, 1);
244- if (stdevArr1 === 0 || stdevArr2 === 0) {
245- throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
246- }
247- return covariance(arr1, arr2) / stdev(arr1, 1) / stdev(arr2, 1);
248-};
249-
250-/**
251- * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
252- * will be ignored. PEARSON is synonymous with CORREL.
253- * @param values[0] data_y - The range representing the array or matrix of dependent data.
254- * @param values[1] data_x - The range representing the array or matrix of independent data.
255- * @returns {number} the Pearson product-moment correlation coefficient.
256- * @constructor
257- */
258-var PEARSON = function (...values) {
259- return CORREL.apply(this, values);
260-};
261-
262-
263 export {
264 ABS,
265 ACOS,
266@@ -1977,9 +1750,6 @@ export {
267 ATAN,
268 ATAN2,
269 ATANH,
270- AVERAGE,
271- AVERAGEA,
272- AVEDEV,
273 COT,
274 COTH,
275 COSH,
276@@ -2002,7 +1772,6 @@ export {
277 ISODD,
278 MAX,
279 MAXA,
280- MEDIAN,
281 MIN,
282 MINA,
283 MOD,
284@@ -2039,7 +1808,5 @@ export {
285 TRUNC,
286 RADIANS,
287 DEGREES,
288- PEARSON,
289- CORREL,
290 COMBIN
291 }
292\ No newline at end of file
293diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
294index 763a5c3..1b18a91 100644
295--- a/src/RawFormulas/RawFormulas.ts
296+++ b/src/RawFormulas/RawFormulas.ts
297@@ -12,9 +12,6 @@ import {
298 ATAN,
299 ATAN2,
300 ATANH,
301- AVERAGE,
302- AVERAGEA,
303- AVEDEV,
304 COT,
305 COTH,
306 COSH,
307@@ -37,7 +34,6 @@ import {
308 ISODD,
309 MAX,
310 MAXA,
311- MEDIAN,
312 MIN,
313 MINA,
314 MOD,
315@@ -74,8 +70,6 @@ import {
316 TRUNC,
317 RADIANS,
318 DEGREES,
319- PEARSON,
320- CORREL,
321 COMBIN
322 } from "./Math";
323 import {
324@@ -104,6 +98,15 @@ import {
325 DOLLARDE,
326 DOLLARFR
327 } from "./Financial";
328+import {
329+ AVERAGE,
330+ AVERAGEA,
331+ AVEDEV,
332+ CORREL,
333+ PEARSON,
334+ MEDIAN
335+} from "./Statistical";
336+
337 import {
338 CriteriaFunctionFactory,
339 ArgsChecker,
340diff --git a/src/RawFormulas/Statistical.ts b/src/RawFormulas/Statistical.ts
341new file mode 100644
342index 0000000..ffb566f
343--- /dev/null
344+++ b/src/RawFormulas/Statistical.ts
345@@ -0,0 +1,249 @@
346+import {
347+ ArgsChecker,
348+ Filter,
349+ TypeCaster
350+} from "./Utils";
351+import {
352+ CellError
353+} from "../Errors";
354+import {
355+ SUM,
356+ ABS
357+} from "./Math"
358+import * as ERRORS from "../Errors";
359+
360+/**
361+ * Returns the median value in a numeric dataset.
362+ * @param values The value(s) or range(s) to consider when calculating the median value.
363+ * @returns {number} the median value of the dataset
364+ * @constructor
365+ */
366+var MEDIAN = function (...values) : number {
367+ ArgsChecker.checkAtLeastLength(values, 1);
368+ var sortedArray = [];
369+ values.forEach(function (currentValue) {
370+ if (currentValue instanceof Array) {
371+ if (currentValue.length === 0) {
372+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
373+ }
374+ var filtered = Filter.filterOutStringValues(currentValue);
375+ sortedArray = sortedArray.concat(filtered);
376+ } else {
377+ sortedArray.push(currentValue);
378+ }
379+ });
380+ sortedArray = sortedArray.sort(function (a, b) {
381+ var aN = TypeCaster.valueToNumber(a);
382+ var bN = TypeCaster.valueToNumber(b);
383+ return aN - bN;
384+ });
385+ if (sortedArray.length === 1) {
386+ return TypeCaster.valueToNumber(sortedArray[0]);
387+ }
388+ if (sortedArray.length === 0) {
389+ throw new CellError(ERRORS.NUM_ERROR, "MEDIAN has no valid input data.");
390+ }
391+ // even number of values
392+ if (sortedArray.length % 2 === 0) {
393+ if (sortedArray.length === 2) {
394+ return AVERAGE(sortedArray[0], sortedArray[1]);
395+ }
396+ var top = sortedArray[sortedArray.length / 2];
397+ var bottom = sortedArray[(sortedArray.length / 2) - 1];
398+ return AVERAGE(top, bottom);
399+ } else {
400+ // odd number of values
401+ return sortedArray[Math.round(sortedArray.length / 2) - 1];
402+ }
403+};
404+
405+/**
406+ * Returns the numerical average value in a dataset, ignoring text.
407+ * @param values The values or ranges to consider when calculating the average value.
408+ * @returns {number} the average value of this dataset.
409+ * @constructor
410+ */
411+var AVERAGE = function (...values) : number {
412+ ArgsChecker.checkAtLeastLength(values, 1);
413+ var result = 0;
414+ var count = 0;
415+ for (var i = 0; i < values.length; i++) {
416+ if (values[i] instanceof Array) {
417+ if (values[i].length === 0) {
418+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
419+ }
420+ var filtered = Filter.filterOutStringValues(values[i]);
421+ result = result + SUM.apply(this, filtered);
422+ count += filtered.length;
423+ } else {
424+ result = result + TypeCaster.valueToNumber(values[i]);
425+ count++;
426+ }
427+ }
428+ return result / count;
429+};
430+
431+/**
432+ * Calculates the average of the magnitudes of deviations of data from a dataset's mean.
433+ * @param values The value(s) or range(s)
434+ * @returns {number} average of the magnitudes of deviations of data from a dataset's mean
435+ * @constructor
436+ */
437+var AVEDEV = function (...values) {
438+ ArgsChecker.checkAtLeastLength(values, 1);
439+
440+ // Sort to array-values, and non-array-values
441+ var arrayValues = [];
442+ var nonArrayValues = [];
443+ for (var i = 0; i < values.length; i++) {
444+ var X = values[i];
445+ if (X instanceof Array) {
446+ if (X.length === 0) {
447+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
448+ }
449+ arrayValues.push(X);
450+ } else {
451+ nonArrayValues.push(TypeCaster.valueToNumber(X));
452+ }
453+ }
454+
455+ // Remove string values from array-values, but not from non-array-values, and concat.
456+ var flatValues = Filter.filterOutStringValues(Filter.flatten(arrayValues)).map(function (value) {
457+ return TypeCaster.valueToNumber(value);
458+ }).concat(nonArrayValues);
459+
460+ // Calculating mean
461+ var result = 0;
462+ var count = 0;
463+ for (var i = 0; i < flatValues.length; i++) {
464+ result = result + TypeCaster.valueToNumber(flatValues[i]);
465+ count++;
466+ }
467+ var mean = result / count;
468+
469+ for (var i = 0; i < flatValues.length; i++) {
470+ flatValues[i] = ABS(TypeCaster.valueToNumber(flatValues[i]) - mean);
471+ }
472+ return SUM(flatValues) / flatValues.length;
473+};
474+
475+/**
476+ * Returns the numerical average value in a dataset, coercing text values in ranges to 0 values.
477+ * @param values value(s) or range(s) to consider when calculating the average value.
478+ * @returns {number} the numerical average value in a dataset
479+ * @constructor
480+ */
481+var AVERAGEA = function (...values) {
482+ ArgsChecker.checkAtLeastLength(values, 1);
483+ var result = 0;
484+ var count = 0;
485+ for (var i = 0; i < values.length; i++) {
486+ if (values[i] instanceof Array) {
487+ if (values[i].length === 0) {
488+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
489+ }
490+ var filtered = Filter.stringValuesToZeros(values[i]);
491+ result = result + SUM.apply(this, filtered);
492+ count += filtered.length;
493+ } else {
494+ result = result + TypeCaster.valueToNumber(values[i]);
495+ count++;
496+ }
497+ }
498+ return result / count;
499+};
500+
501+/**
502+ * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
503+ * will be ignored. CORREL is synonymous with PEARSON.
504+ * @param values[0] data_y - The range representing the array or matrix of dependent data.
505+ * @param values[1] data_x - The range representing the array or matrix of independent data.
506+ * @returns {number} the Pearson product-moment correlation coefficient.
507+ * @constructor
508+ */
509+var CORREL = function (...values) : number {
510+ function stdev(arr, flag) {
511+ return Math.sqrt(variance(arr, flag));
512+ }
513+ function variance(arr, flag) {
514+ if ((arr.length - (flag ? 1 : 0)) === 0) {
515+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
516+ }
517+ return sumsqerr(arr) / (arr.length - (flag ? 1 : 0));
518+ }
519+ function sum(arr) {
520+ var sum = 0;
521+ var i = arr.length;
522+ while (--i >= 0) {
523+ sum += arr[i];
524+ }
525+ return sum;
526+ }
527+ function mean(arr) {
528+ return sum(arr) / arr.length;
529+ }
530+ function sumsqerr(arr) {
531+ var m = mean(arr);
532+ var sum = 0;
533+ var i = arr.length;
534+ var tmp;
535+ while (--i >= 0) {
536+ tmp = arr[i] - m;
537+ sum += tmp * tmp;
538+ }
539+ return sum;
540+ }
541+ function covariance(arr1, arr2) {
542+ var u = mean(arr1);
543+ var v = mean(arr2);
544+ var arr1Len = arr1.length;
545+ var sq_dev = new Array(arr1Len);
546+ for (var i = 0; i < arr1Len; i++) {
547+ sq_dev[i] = (arr1[i] - u) * (arr2[i] - v);
548+ }
549+ if ((arr1Len - 1) === 0) {
550+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
551+ }
552+ return sum(sq_dev) / (arr1Len - 1);
553+ }
554+ ArgsChecker.checkLength(values, 2);
555+ if (!Array.isArray(values[0])) {
556+ values[0] = [values[0]];
557+ }
558+ if (!Array.isArray(values[1])) {
559+ values[1] = [values[1]];
560+ }
561+ if (values[0].length !== values[1].length) {
562+ throw new CellError(ERRORS.NA_ERROR, "CORREL has mismatched argument count " + values[0] + " vs " + values[1] + ".");
563+ }
564+ var arr1 = Filter.filterOutNonNumberValues(Filter.flattenAndThrow(values[0]));
565+ var arr2 = Filter.filterOutNonNumberValues(Filter.flattenAndThrow(values[1]));
566+ var stdevArr1 = stdev(arr1, 1);
567+ var stdevArr2 = stdev(arr2, 1);
568+ if (stdevArr1 === 0 || stdevArr2 === 0) {
569+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
570+ }
571+ return covariance(arr1, arr2) / stdev(arr1, 1) / stdev(arr2, 1);
572+};
573+
574+/**
575+ * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
576+ * will be ignored. PEARSON is synonymous with CORREL.
577+ * @param values[0] data_y - The range representing the array or matrix of dependent data.
578+ * @param values[1] data_x - The range representing the array or matrix of independent data.
579+ * @returns {number} the Pearson product-moment correlation coefficient.
580+ * @constructor
581+ */
582+var PEARSON = function (...values) {
583+ return CORREL.apply(this, values);
584+};
585+
586+
587+export {
588+ AVERAGE,
589+ AVERAGEA,
590+ AVEDEV,
591+ CORREL,
592+ PEARSON,
593+ MEDIAN
594+}
595\ No newline at end of file