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