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);