commit
message
[SLOPE] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-06-23 02:41:44
stats
8 file(s) changed,
114 insertions(+),
5 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 6dced99..8199e0d 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -1507,6 +1507,15 @@
6 @returns {number}
7 @constructor
8 ```
9+
10+### SLOPE
11+
12+```
13+ Returns the slope of the line calculated from linear regression of a range. Any text values passed in will be ignored
14+@param rangeY - The range or array representing the dependent data.
15+@param rangeX - The range or array representing the independent data.
16+@constructor
17+```
18 ## Text
19
20
21diff --git a/TODO.md b/TODO.md
22index 80e1b53..57f5868 100644
23--- a/TODO.md
24+++ b/TODO.md
25@@ -90,7 +90,6 @@ For example 64 tbs to a qt.
26 * RANK.EQ
27 * RSQ
28 * SKEW
29-* SLOPE
30 * SMALL
31 * STANDARDIZE
32 * STEYX
33diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
34index aeabfdb..60e0a5c 100644
35--- a/dist/Formulas/AllFormulas.js
36+++ b/dist/Formulas/AllFormulas.js
37@@ -136,6 +136,7 @@ exports.STDEVA = Statistical_1.STDEVA;
38 exports.STDEVP = Statistical_1.STDEVP;
39 exports.STDEVPA = Statistical_1.STDEVPA;
40 exports.TRIMMEAN = Statistical_1.TRIMMEAN;
41+exports.SLOPE = Statistical_1.SLOPE;
42 var Text_1 = require("./Text");
43 exports.ARABIC = Text_1.ARABIC;
44 exports.CHAR = Text_1.CHAR;
45diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
46index d8e123a..8cd1552 100644
47--- a/dist/Formulas/Statistical.js
48+++ b/dist/Formulas/Statistical.js
49@@ -723,3 +723,39 @@ var TRIMMEAN = function (range, percent) {
50 return MathHelpers_1.mean(tmp.slice(0, tmp.length - trim));
51 };
52 exports.TRIMMEAN = TRIMMEAN;
53+/**
54+ * Returns the slope of the line calculated from linear regression of a range. Any text values passed in will be ignored
55+ * @param rangeY - The range or array representing the dependent data.
56+ * @param rangeX - The range or array representing the independent data.
57+ * @constructor
58+ */
59+var SLOPE = function (rangeY, rangeX) {
60+ ArgsChecker_1.ArgsChecker.checkLength(arguments, 2, "SLOPE");
61+ var dataX = Filter_1.Filter.flattenAndThrow(rangeX).filter(function (value) {
62+ return typeof value !== "string";
63+ }).map(function (value) {
64+ return TypeConverter_1.TypeConverter.valueToNumber(value);
65+ });
66+ var dataY = Filter_1.Filter.flattenAndThrow(rangeY).filter(function (value) {
67+ return typeof value !== "string";
68+ }).map(function (value) {
69+ return TypeConverter_1.TypeConverter.valueToNumber(value);
70+ });
71+ if (dataX.length !== dataY.length) {
72+ throw new Errors_1.NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
73+ }
74+ var xmean = MathHelpers_1.mean(dataX);
75+ var ymean = MathHelpers_1.mean(dataY);
76+ var n = dataX.length;
77+ var num = 0;
78+ var den = 0;
79+ for (var i = 0; i < n; i++) {
80+ num += (dataX[i] - xmean) * (dataY[i] - ymean);
81+ den += Math.pow(dataX[i] - xmean, 2);
82+ }
83+ if (den === 0) {
84+ throw new Errors_1.DivZeroError("Evaluation of function SLOPE caused a divide by zero error.");
85+ }
86+ return num / den;
87+};
88+exports.SLOPE = SLOPE;
89diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
90index 70c9a0d..a3d63ca 100644
91--- a/src/Formulas/AllFormulas.ts
92+++ b/src/Formulas/AllFormulas.ts
93@@ -141,7 +141,8 @@ import {
94 STDEVA,
95 STDEVP,
96 STDEVPA,
97- TRIMMEAN
98+ TRIMMEAN,
99+ SLOPE
100 } from "./Statistical";
101 import {
102 ARABIC,
103@@ -347,5 +348,6 @@ export {
104 FACTDOUBLE,
105 FREQUENCY,
106 GROWTH,
107- TRIMMEAN
108+ TRIMMEAN,
109+ SLOPE
110 }
111\ No newline at end of file
112diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
113index b6bbe82..c400066 100644
114--- a/src/Formulas/Statistical.ts
115+++ b/src/Formulas/Statistical.ts
116@@ -703,6 +703,43 @@ var TRIMMEAN = function (range, percent) {
117 };
118
119
120+/**
121+ * Returns the slope of the line calculated from linear regression of a range. Any text values passed in will be ignored
122+ * @param rangeY - The range or array representing the dependent data.
123+ * @param rangeX - The range or array representing the independent data.
124+ * @constructor
125+ */
126+var SLOPE = function (rangeY, rangeX) {
127+ ArgsChecker.checkLength(arguments, 2, "SLOPE");
128+ var dataX = Filter.flattenAndThrow(rangeX).filter(function (value) {
129+ return typeof value !== "string";
130+ }).map(function (value) {
131+ return TypeConverter.valueToNumber(value);
132+ });
133+ var dataY = Filter.flattenAndThrow(rangeY).filter(function (value) {
134+ return typeof value !== "string";
135+ }).map(function (value) {
136+ return TypeConverter.valueToNumber(value);
137+ });
138+ if (dataX.length !== dataY.length) {
139+ throw new NAError("SLOPE has mismatched argument count " + dataX.length + " vs " + dataY.length + ".");
140+ }
141+ var xmean = mean(dataX);
142+ var ymean = mean(dataY);
143+ var n = dataX.length;
144+ var num = 0;
145+ var den = 0;
146+ for (var i = 0; i < n; i++) {
147+ num += (dataX[i] - xmean) * (dataY[i] - ymean);
148+ den += Math.pow(dataX[i] - xmean, 2);
149+ }
150+ if (den === 0) {
151+ throw new DivZeroError("Evaluation of function SLOPE caused a divide by zero error.");
152+ }
153+ return num / den;
154+};
155+
156+
157 export {
158 AVERAGE,
159 AVERAGEA,
160@@ -729,5 +766,6 @@ export {
161 STDEVA,
162 STDEVP,
163 STDEVPA,
164- TRIMMEAN
165+ TRIMMEAN,
166+ SLOPE
167 }
168\ No newline at end of file
169diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
170index 65c5aaa..cebdb11 100644
171--- a/tests/Formulas/StatisticalTest.ts
172+++ b/tests/Formulas/StatisticalTest.ts
173@@ -24,7 +24,8 @@ import {
174 STDEVA,
175 STDEVP,
176 STDEVPA,
177- TRIMMEAN
178+ TRIMMEAN,
179+ SLOPE
180 } from "../../src/Formulas/Statistical";
181 import * as ERRORS from "../../src/Errors";
182 import {
183@@ -568,4 +569,21 @@ test("TRIMMEAN", function() {
184 catchAndAssertEquals(function() {
185 TRIMMEAN([10], -1);
186 }, ERRORS.NUM_ERROR);
187+});
188+
189+test("SLOPE", function() {
190+ assertEquals(SLOPE([1, 2.2, 4, 5.5, 6, 8], [1.9, 22.2, 44, 55.5, 88, 99.1]), 0.06727907586278936);
191+ assertEquals(SLOPE([1.1, 2.44, 5, 10.5, 600, 800], [1.9, 22.2, 44, 55.5, 88, 99.1]), 8.50783378332324);
192+ assertEquals(SLOPE([1.1, 2.44, 5, 10.5, 600, "ignore", 800], [1.9, 22.2, 44, 55.5, 88, 99.1]), 8.50783378332324);
193+ assertEquals(SLOPE([600, 800], [44, 4.1]), -5.012531328320802);
194+ assertEquals(SLOPE([1, 2.2, 4, 5.5, 6, 8, true], [1.9, 22.2, 44, 55.5, 88, 99.1, true]), 0.06743685772979165);
195+ catchAndAssertEquals(function() {
196+ SLOPE([1], [0]);
197+ }, ERRORS.DIV_ZERO_ERROR);
198+ catchAndAssertEquals(function() {
199+ SLOPE([1], [1]);
200+ }, ERRORS.DIV_ZERO_ERROR);
201+ catchAndAssertEquals(function() {
202+ SLOPE([1, 3], [1]);
203+ }, ERRORS.NA_ERROR);
204 });
205\ No newline at end of file
206diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
207index 312d32e..def495a 100644
208--- a/tests/SheetFormulaTest.ts
209+++ b/tests/SheetFormulaTest.ts
210@@ -691,6 +691,10 @@ test("Sheet TRIMMEAN", function(){
211 assertFormulaEquals('=TRIMMEAN([1], 0.1)', 1);
212 });
213
214+test("Sheet SLOPE", function(){
215+ assertFormulaEquals('=SLOPE([600, 800], [44, 4.1])', -5.012531328320802);
216+});
217+
218 test("Sheet *", function(){
219 assertFormulaEquals('= 10 * 10', 100);
220 assertFormulaEquals('= 10 * 0', 0);