spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[STEYX] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-12 02:50:15
stats
8 file(s) changed, 129 insertions(+), 30 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 21bc223..c9f4d4c 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -2048,6 +2048,16 @@
  6 @returns {number} 
  7 @constructor
  8 ```
  9+
 10+### STEYX 
 11+
 12+```
 13+  Returns the standard error of the predicted y value for each x in the regression. Text values will be ignored. 
 14+@param rangeY - An array or range of data points. 
 15+@param rangeX - An array or range of data points. 
 16+@returns {number} 
 17+@constructor
 18+```
 19 ## Text
 20 
 21 
 22diff --git a/TODO.md b/TODO.md
 23index 1237d07..5f1ecd4 100644
 24--- a/TODO.md
 25+++ b/TODO.md
 26@@ -70,7 +70,6 @@ Many of these formulas can be written by allowing the Sheet and Parser to return
 27 * RANK
 28 * RANK.AVG
 29 * RANK.EQ
 30-* STEYX
 31 * T.INV
 32 * T.INV.2T
 33 * TDIST
 34diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 35index 7a2480d..9eafc38 100644
 36--- a/dist/Formulas/AllFormulas.js
 37+++ b/dist/Formulas/AllFormulas.js
 38@@ -190,6 +190,7 @@ exports.VAR = Statistical_1.VAR;
 39 exports.PERMUT = Statistical_1.PERMUT;
 40 exports.RSQ = Statistical_1.RSQ;
 41 exports.SKEW = Statistical_1.SKEW;
 42+exports.STEYX = Statistical_1.STEYX;
 43 var Text_1 = require("./Text");
 44 exports.ARABIC = Text_1.ARABIC;
 45 exports.CHAR = Text_1.CHAR;
 46diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
 47index 284584a..14196d3 100644
 48--- a/dist/Formulas/Statistical.js
 49+++ b/dist/Formulas/Statistical.js
 50@@ -1706,16 +1706,8 @@ var RSQ = function (rangeY, rangeX) {
 51     if (!Array.isArray(rangeX)) {
 52         rangeX = [rangeX];
 53     }
 54-    var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
 55-        return typeof value !== "string";
 56-    }).map(function (value) {
 57-        return TypeConverter_1.TypeConverter.valueToNumber(value);
 58-    });
 59-    var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
 60-        return typeof value !== "string";
 61-    }).map(function (value) {
 62-        return TypeConverter_1.TypeConverter.valueToNumber(value);
 63-    });
 64+    var dataX = Filter_1.Filter.flattenAndThrow(rangeX).map(TypeConverter_1.TypeConverter.valueToNumber);
 65+    var dataY = Filter_1.Filter.flattenAndThrow(rangeY).map(TypeConverter_1.TypeConverter.valueToNumber);
 66     if (dataX.length !== dataY.length) {
 67         throw new Errors_1.NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
 68     }
 69@@ -1754,3 +1746,44 @@ var SKEW = function () {
 70     return n * sigma / d;
 71 };
 72 exports.SKEW = SKEW;
 73+/**
 74+ * Returns the standard error of the predicted y value for each x in the regression. Text values will be ignored.
 75+ * @param rangeY - An array or range of data points.
 76+ * @param rangeX - An array or range of data points.
 77+ * @returns {number}
 78+ * @constructor
 79+ */
 80+var STEYX = function (rangeY, rangeX) {
 81+    ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "STEYX");
 82+    if (!Array.isArray(rangeY)) {
 83+        rangeY = [rangeY];
 84+    }
 85+    if (!Array.isArray(rangeX)) {
 86+        rangeX = [rangeX];
 87+    }
 88+    var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
 89+        return typeof value !== "string";
 90+    }).map(TypeConverter_1.TypeConverter.valueToNumber);
 91+    var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
 92+        return typeof value !== "string";
 93+    }).map(TypeConverter_1.TypeConverter.valueToNumber);
 94+    if (dataX.length !== dataY.length) {
 95+        throw new Errors_1.NAError("STEYX has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
 96+    }
 97+    if (dataY.length === 2 && dataX.length === 2) {
 98+        throw new Errors_1.DivZeroError("Evaluation of function STEYX caused a divide by zero error.");
 99+    }
100+    var xmean = MathHelpers_1.mean(dataX);
101+    var ymean = MathHelpers_1.mean(dataY);
102+    var n = dataX.length;
103+    var lft = 0;
104+    var num = 0;
105+    var den = 0;
106+    for (var i = 0; i < n; i++) {
107+        lft += Math.pow(dataY[i] - ymean, 2);
108+        num += (dataX[i] - xmean) * (dataY[i] - ymean);
109+        den += Math.pow(dataX[i] - xmean, 2);
110+    }
111+    return Math.sqrt((lft - num * num / den) / (n - 2));
112+};
113+exports.STEYX = STEYX;
114diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
115index 5dba7a9..dc1b6c7 100644
116--- a/src/Formulas/AllFormulas.ts
117+++ b/src/Formulas/AllFormulas.ts
118@@ -195,7 +195,8 @@ import {
119   VAR,
120   PERMUT,
121   RSQ,
122-  SKEW
123+  SKEW,
124+  STEYX
125 } from "./Statistical";
126 import {
127   ARABIC,
128@@ -465,5 +466,6 @@ export {
129   VAR,
130   PERMUT,
131   RSQ,
132-  SKEW
133+  SKEW,
134+  STEYX
135 }
136\ No newline at end of file
137diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
138index 95c9968..756f04c 100644
139--- a/src/Formulas/Statistical.ts
140+++ b/src/Formulas/Statistical.ts
141@@ -1689,16 +1689,8 @@ var RSQ = function (rangeY, rangeX) {
142   if (!Array.isArray(rangeX)) {
143     rangeX = [rangeX];
144   }
145-  var dataX = Filter.flattenAndThrow(rangeX).filter(function (value) {
146-    return typeof value !== "string";
147-  }).map(function (value) {
148-    return TypeConverter.valueToNumber(value);
149-  });
150-  var dataY = Filter.flattenAndThrow(rangeY).filter(function (value) {
151-    return typeof value !== "string";
152-  }).map(function (value) {
153-    return TypeConverter.valueToNumber(value);
154-  });
155+  var dataX = Filter.flattenAndThrow(rangeX).map(TypeConverter.valueToNumber);
156+  var dataY = Filter.flattenAndThrow(rangeY).map(TypeConverter.valueToNumber);
157   if (dataX.length !== dataY.length) {
158     throw new NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
159   }
160@@ -1735,6 +1727,48 @@ var SKEW = function (...values) {
161 };
162 
163 
164+/**
165+ * Returns the standard error of the predicted y value for each x in the regression. Text values will be ignored.
166+ * @param rangeY - An array or range of data points.
167+ * @param rangeX - An array or range of data points.
168+ * @returns {number}
169+ * @constructor
170+ */
171+var STEYX =  function (rangeY, rangeX) {
172+  ArgsChecker.checkLength(arguments, 2, "STEYX");
173+  if (!Array.isArray(rangeY)) {
174+    rangeY = [rangeY];
175+  }
176+  if (!Array.isArray(rangeX)) {
177+    rangeX = [rangeX];
178+  }
179+  var dataX = Filter.flattenAndThrow(rangeX).filter(function (value) {
180+    return typeof value !== "string";
181+  }).map(TypeConverter.valueToNumber);
182+  var dataY = Filter.flattenAndThrow(rangeY).filter(function (value) {
183+    return typeof value !== "string";
184+  }).map(TypeConverter.valueToNumber);
185+  if (dataX.length !== dataY.length) {
186+    throw new NAError("STEYX has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
187+  }
188+  if (dataY.length === 2 && dataX.length === 2) {
189+    throw new DivZeroError("Evaluation of function STEYX caused a divide by zero error.");
190+  }
191+  var xmean = mean(dataX);
192+  var ymean = mean(dataY);
193+  var n = dataX.length;
194+  var lft = 0;
195+  var num = 0;
196+  var den = 0;
197+  for (var i = 0; i < n; i++) {
198+    lft += Math.pow(dataY[i] - ymean, 2);
199+    num += (dataX[i] - xmean) * (dataY[i] - ymean);
200+    den += Math.pow(dataX[i] - xmean, 2);
201+  }
202+  return Math.sqrt((lft - num * num / den) / (n - 2));
203+};
204+
205+
206 export {
207   AVERAGE,
208   AVERAGEA,
209@@ -1789,5 +1823,6 @@ export {
210   VAR,
211   PERMUT,
212   RSQ,
213-  SKEW
214+  SKEW,
215+  STEYX
216 }
217\ No newline at end of file
218diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
219index 5caedd1..9c4287f 100644
220--- a/tests/Formulas/StatisticalTest.ts
221+++ b/tests/Formulas/StatisticalTest.ts
222@@ -52,7 +52,8 @@ import {
223   VAR,
224   PERMUT,
225   RSQ,
226-  SKEW
227+  SKEW,
228+  STEYX
229 } from "../../src/Formulas/Statistical";
230 import * as ERRORS from "../../src/Errors";
231 import {
232@@ -1071,4 +1072,22 @@ test("SKEW", function() {
233   catchAndAssertEquals(function() {
234     SKEW.apply(this, []);
235   }, ERRORS.NA_ERROR);
236+});
237+
238+test("STEYX", function() {
239+  assertEquals(STEYX([1, 2, 3, 4], [1, 3, 5, 2]), 1.4638501094227998);
240+  assertEquals(STEYX([1, 2, 3, 4, "str"], [1, 3, 5, 2, "str"]), 1.4638501094227998);
241+  assertEquals(STEYX([1, 2, 3], [1, 3, 5]), 0);
242+  catchAndAssertEquals(function() {
243+    STEYX([1, 2], [1, 3]);
244+  }, ERRORS.DIV_ZERO_ERROR);
245+  catchAndAssertEquals(function() {
246+    STEYX([1, 2, 3, 4], [1, 2, 3]);
247+  }, ERRORS.NA_ERROR);
248+  catchAndAssertEquals(function() {
249+    STEYX.apply(this, [[1, 2, 3]]);
250+  }, ERRORS.NA_ERROR);
251+  catchAndAssertEquals(function() {
252+    STEYX.apply(this, [[1, 2, 3], [1, 2, 3], [1, 2, 3]]);
253+  }, ERRORS.NA_ERROR);
254 });
255\ No newline at end of file
256diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
257index 6356ae3..5ed0f3a 100644
258--- a/tests/SheetFormulaTest.ts
259+++ b/tests/SheetFormulaTest.ts
260@@ -918,6 +918,10 @@ test("Sheet SKEW", function(){
261   assertFormulaEquals('=SKEW(1, 2, 3, 4, 5, 6, 100)', 2.6336050735387375);
262 });
263 
264+test("Sheet STEYX", function(){
265+  assertFormulaEquals('=STEYX([1, 2, 3, 4], [1, 3, 5, 2])', 1.4638501094227998);
266+});
267+
268 test("Sheet *", function(){
269   assertFormulaEquals('= 10 * 10', 100);
270   assertFormulaEquals('= 10 * 0', 0);