Add "average" filter operator for arithmetic mean (#5612)

new-json-store-area
Jeremy Ruston 2021-04-27 10:09:13 +01:00 zatwierdzone przez GitHub
rodzic 4a99e0cc7d
commit bf773eb39a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
11 zmienionych plików z 193 dodań i 8 usunięć

Wyświetl plik

@ -125,6 +125,54 @@ exports.minall = makeNumericReducingOperator(
Infinity // Initial value
);
exports.median = makeNumericArrayOperator(
function(values) {
var len = values.length, median;
values.sort();
if(len % 2) {
// Odd, return the middle number
median = values[(len - 1) / 2];
} else {
// Even, return average of two middle numbers
median = (values[len / 2 - 1] + values[len / 2]) / 2;
}
return [median];
}
);
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 = [],
@ -134,19 +182,37 @@ function makeNumericBinaryOperator(fnCalc) {
});
return result;
};
}
};
function makeNumericReducingOperator(fnCalc,initialValue) {
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));
});
return [$tw.utils.stringifyNumber(result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,$tw.utils.parseNumber(currentValue));
},initialValue))];
var value = result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,currentValue);
},initialValue);
if(fnFinal) {
value = fnFinal(value,result.length,result);
}
return [$tw.utils.stringifyNumber(value)];
};
}
};
function makeNumericArrayOperator(fnCalc) {
return function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.parseNumber(title));
});
results = fnCalc(results);
$tw.utils.each(results,function(value,index) {
results[index] = $tw.utils.stringifyNumber(value);
});
return results;
};
};
})();

Wyświetl plik

@ -298,6 +298,28 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
expect(wiki.filterTiddlers("[tag[non-existent]reduce<add-price>else[0]]",anchorWidget).join(",")).toBe("0");
});
it("should handle the average operator", function() {
expect(wiki.filterTiddlers("[tag[shopping]get[price]average[]]").join(",")).toBe("2.3575");
expect(parseFloat(wiki.filterTiddlers("[tag[food]get[price]average[]]").join(","))).toBeCloseTo(3.155);
});
it("should handle the median operator", 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");
expect(wiki.filterTiddlers("[[Brownies]tags[]] :intersection[[Chocolate Cake]tags[]]").join(",")).toBe("food");

Wyświetl plik

@ -1,5 +1,5 @@
created: 20190206140446821
modified: 20190611155838557
modified: 20210417090408263
tags: Filters
title: Mathematics Operators
type: text/vnd.tiddlywiki
@ -26,6 +26,7 @@ The mathematics operators take three different forms:
* ''Reducing operators'' apply an operation to all of the numbers in the input list, returning a single result (e.g. sum, product)
** <<.inline-operator-example "=1 =2 =3 =4 +[sum[]]">>
** <<.inline-operator-example "=1 =2 =3 =4 +[product[]]">>
** <<.inline-operator-example "=1 =2 =3 =4 +[average[]]">>
Operators can be combined:

Wyświetl plik

@ -0,0 +1,13 @@
caption: average
created: 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
tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Operators]]
title: average Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.operator-examples "average">>

Wyświetl plik

@ -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[]]">>

Wyświetl plik

@ -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[]]">>

Wyświetl plik

@ -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[]]">>

Wyświetl plik

@ -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[]]">>

Wyświetl plik

@ -0,0 +1,13 @@
caption: median
created: 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
tags: [[Filter Operators]] [[Mathematics Operators]]
title: median Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.operator-examples "median">>

Wyświetl plik

@ -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">>

Wyświetl plik

@ -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">>