From fab773a151787e21ea83f54c28da0c6158ee3e2f Mon Sep 17 00:00:00 2001 From: Saq Imtiaz Date: Tue, 27 Apr 2021 10:58:04 +0200 Subject: [PATCH] Added variance and standard-deviation operators and docs. Also added examples in docs for median and average operator (#5645) --- core/modules/filters/math.js | 53 ++++++++++++++----- .../tiddlers/tests/test-prefixes-filter.js | 12 +++++ editions/tw5.com/tiddlers/filters/average.tid | 4 +- .../examples/average Operator (Examples).tid | 10 ++++ .../examples/median Operator (Examples).tid | 10 ++++ ...standard-deviation Operator (Examples).tid | 10 ++++ .../examples/variance Operator (Examples).tid | 10 ++++ editions/tw5.com/tiddlers/filters/median.tid | 4 +- .../filters/standard-deviation Operator.tid | 15 ++++++ .../tiddlers/filters/variance Operator.tid | 15 ++++++ 10 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/examples/average Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/median Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/standard-deviation Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/variance Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/standard-deviation Operator.tid create mode 100644 editions/tw5.com/tiddlers/filters/variance Operator.tid diff --git a/core/modules/filters/math.js b/core/modules/filters/math.js index e45811eda..9e767c362 100644 --- a/core/modules/filters/math.js +++ b/core/modules/filters/math.js @@ -125,14 +125,6 @@ exports.minall = makeNumericReducingOperator( Infinity // Initial value ); -exports.average = makeNumericReducingOperator( - function(accumulator,value) {return accumulator + value}, - 0, // Initial value - function(finalValue,numberOfValues) { - return finalValue/numberOfValues; - } -); - exports.median = makeNumericArrayOperator( function(values) { var len = values.length, median; @@ -148,6 +140,39 @@ exports.median = makeNumericArrayOperator( } ); +exports.average = makeNumericReducingOperator( + function(accumulator,value) {return accumulator + value}, + 0, // Initial value + function(finalValue,numberOfValues) { + return finalValue/numberOfValues; + } +); + +exports.variance = makeNumericReducingOperator( + function(accumulator,value) {return accumulator + value}, + 0, + function(finalValue,numberOfValues,originalValues) { + return getVarianceFromArray(originalValues,finalValue/numberOfValues); + } +); + +exports["standard-deviation"] = makeNumericReducingOperator( + function(accumulator,value) {return accumulator + value}, + 0, + function(finalValue,numberOfValues,originalValues) { + var variance = getVarianceFromArray(originalValues,finalValue/numberOfValues); + return Math.sqrt(variance); + } +); + +//Calculate the variance of a population of numbers in an array given its mean +function getVarianceFromArray(values,mean) { + var deviationTotal = values.reduce(function(accumulator,value) { + return accumulator + Math.pow(value - mean, 2); + },0); + return deviationTotal/values.length; +}; + function makeNumericBinaryOperator(fnCalc) { return function(source,operator,options) { var result = [], @@ -157,24 +182,24 @@ function makeNumericBinaryOperator(fnCalc) { }); return result; }; -} +}; function makeNumericReducingOperator(fnCalc,initialValue,fnFinal) { initialValue = initialValue || 0; return function(source,operator,options) { var result = []; source(function(tiddler,title) { - result.push(title); + result.push($tw.utils.parseNumber(title)); }); var value = result.reduce(function(accumulator,currentValue) { - return fnCalc(accumulator,$tw.utils.parseNumber(currentValue)); + return fnCalc(accumulator,currentValue); },initialValue); if(fnFinal) { - value = fnFinal(value,result.length); + value = fnFinal(value,result.length,result); } return [$tw.utils.stringifyNumber(value)]; }; -} +}; function makeNumericArrayOperator(fnCalc) { return function(source,operator,options) { @@ -188,6 +213,6 @@ function makeNumericArrayOperator(fnCalc) { }); return results; }; -} +}; })(); diff --git a/editions/test/tiddlers/tests/test-prefixes-filter.js b/editions/test/tiddlers/tests/test-prefixes-filter.js index 3d770c28f..62dc2a4d0 100644 --- a/editions/test/tiddlers/tests/test-prefixes-filter.js +++ b/editions/test/tiddlers/tests/test-prefixes-filter.js @@ -110,6 +110,18 @@ describe("'reduce' and 'intersection' filter prefix tests", function() { expect(parseFloat(wiki.filterTiddlers("[tag[shopping]get[price]median[]]").join(","))).toBeCloseTo(1.99); expect(parseFloat(wiki.filterTiddlers("[tag[food]get[price]median[]]").join(","))).toBeCloseTo(3.155); }); + + it("should handle the variance operator", function() { + expect(parseFloat(wiki.filterTiddlers("[tag[shopping]get[price]variance[]]").join(","))).toBeCloseTo(2.92); + expect(parseFloat(wiki.filterTiddlers("[tag[food]get[price]variance[]]").join(","))).toBeCloseTo(3.367); + expect(wiki.filterTiddlers(" +[variance[]]").toString()).toBe("NaN"); + }); + + it("should handle the standard-deviation operator", function() { + expect(parseFloat(wiki.filterTiddlers("[tag[shopping]get[price]standard-deviation[]]").join(","))).toBeCloseTo(1.71); + expect(parseFloat(wiki.filterTiddlers("[tag[food]get[price]standard-deviation[]]").join(","))).toBeCloseTo(1.835); + expect(wiki.filterTiddlers(" +[standard-deviation[]]").toString()).toBe("NaN"); + }); it("should handle the :intersection prefix", function() { expect(wiki.filterTiddlers("[[Sparkling water]tags[]] :intersection[[Red wine]tags[]]").join(",")).toBe("drinks,textexample"); diff --git a/editions/tw5.com/tiddlers/filters/average.tid b/editions/tw5.com/tiddlers/filters/average.tid index 5bf08ce1d..36f39be1d 100644 --- a/editions/tw5.com/tiddlers/filters/average.tid +++ b/editions/tw5.com/tiddlers/filters/average.tid @@ -1,6 +1,6 @@ -caption: 20210417090137714 +caption: average created: 20210417090137714 -modified: 20210417090137714 +modified: 20210426131553482 op-input: a [[selection of titles|Title Selection]] op-output: the arithmetic mean of the input as numbers op-purpose: treating each input title as a number, compute their arithmetic mean diff --git a/editions/tw5.com/tiddlers/filters/examples/average Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/average Operator (Examples).tid new file mode 100644 index 000000000..68fb03694 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/average Operator (Examples).tid @@ -0,0 +1,10 @@ +created: 20210426130837644 +modified: 20210426131553546 +tags: [[Operator Examples]] [[average Operator]] +title: average Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 "=1 =3 =4 =5 +[average[]]">> + +Note that if there is no input the operator returns `NaN` +<<.operator-example 2 "[tag[NotATiddler]get[price]] +[average[]]">> diff --git a/editions/tw5.com/tiddlers/filters/examples/median Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/median Operator (Examples).tid new file mode 100644 index 000000000..ed76964b3 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/median Operator (Examples).tid @@ -0,0 +1,10 @@ +created: 20210426131042769 +modified: 20210426131553560 +tags: [[Operator Examples]] [[median Operator]] +title: median Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 "=1 =3 =4 =5 +[median[]]">> + +Note that if there is no input the operator returns `NaN` +<<.operator-example 2 "[title[NotATiddler]get[price]] +[median[]]">> diff --git a/editions/tw5.com/tiddlers/filters/examples/standard-deviation Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/standard-deviation Operator (Examples).tid new file mode 100644 index 000000000..4290287d8 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/standard-deviation Operator (Examples).tid @@ -0,0 +1,10 @@ +created: 20210426130306824 +modified: 20210426131553553 +tags: [[Operator Examples]] [[standard-deviation Operator]] +title: standard-deviation Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 "=1 =3 =4 =5 +[standard-deviation[]]">> + +Note that if there is no input the operator returns `NaN` +<<.operator-example 2 "[title[NotATiddler]get[price]] +[standard-deviation[]]">> diff --git a/editions/tw5.com/tiddlers/filters/examples/variance Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/variance Operator (Examples).tid new file mode 100644 index 000000000..fd0ad07a8 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/variance Operator (Examples).tid @@ -0,0 +1,10 @@ +created: 20210426130620777 +modified: 20210426131553522 +tags: [[Operator Examples]] [[variance Operator]] +title: variance Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 "1 3 4 5 +[variance[]]">> + +Note that if there is no input the operator returns `NaN` +<<.operator-example 2 "[title[NotATiddler]is[tiddler]get[price]] +[variance[]]">> diff --git a/editions/tw5.com/tiddlers/filters/median.tid b/editions/tw5.com/tiddlers/filters/median.tid index f01e86ba8..da8b6acc4 100644 --- a/editions/tw5.com/tiddlers/filters/median.tid +++ b/editions/tw5.com/tiddlers/filters/median.tid @@ -1,6 +1,6 @@ -caption: 20210417090137714 +caption: median created: 20210417090137714 -modified: 20210417090137714 +modified: 20210426131553507 op-input: a [[selection of titles|Title Selection]] op-output: the median of the input numbers op-purpose: treating each input title as a number, compute their median value diff --git a/editions/tw5.com/tiddlers/filters/standard-deviation Operator.tid b/editions/tw5.com/tiddlers/filters/standard-deviation Operator.tid new file mode 100644 index 000000000..125c043b1 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/standard-deviation Operator.tid @@ -0,0 +1,15 @@ +caption: standard-deviation +created: 20210426130150358 +modified: 20210426131553530 +op-input: a [[selection of titles|Title Selection]] +op-output: the standard-deviation of the input as numbers +op-purpose: treating each input title as a number, compute their standard-deviation +tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Operators]] +title: standard-deviation Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview. + +<<.tip """ The `standard-deviation` operator treats the input as a complete population and not a sample""">> + +<<.operator-examples "standard-deviation">> diff --git a/editions/tw5.com/tiddlers/filters/variance Operator.tid b/editions/tw5.com/tiddlers/filters/variance Operator.tid new file mode 100644 index 000000000..913eb2943 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/variance Operator.tid @@ -0,0 +1,15 @@ +caption: variance +created: 20210426130029500 +modified: 20210426131553539 +op-input: a [[selection of titles|Title Selection]] +op-output: the variance of the input as numbers +op-purpose: treating each input title as a number, compute their variance +tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Operators]] +title: variance Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview. + +<<.tip """ The `standard-deviation` operator treats the input as a complete population and not a sample""">> + +<<.operator-examples "variance">>