Skip to content

Commit

Permalink
replace geomean with geometric mean or geometricMean
Browse files Browse the repository at this point in the history
fix geometricMean computation
  • Loading branch information
acxz committed Jul 8, 2022
1 parent 9da8b07 commit 447021b
Show file tree
Hide file tree
Showing 7 changed files with 18 additions and 18 deletions.
2 changes: 1 addition & 1 deletion draftlogs/6223_add.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
- Add geomean functionality and 'geomean ascending' + 'geomean descending' to `category_order` on cartesian axes [[#6223](https://github.com/plotly/plotly.js/pull/6223)]
- Add geometric mean functionality and 'geometric mean ascending' + 'geometric mean descending' to `category_order` on cartesian axes [[#6223](https://github.com/plotly/plotly.js/pull/6223)]
with thanks to @acxz and @prabhathc for the contribution!
2 changes: 1 addition & 1 deletion src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ var statsModule = require('./stats');
lib.aggNums = statsModule.aggNums;
lib.len = statsModule.len;
lib.mean = statsModule.mean;
lib.geoMean = statsModule.geoMean;
lib.geometricMean = statsModule.geometricMean;
lib.median = statsModule.median;
lib.midRange = statsModule.midRange;
lib.variance = statsModule.variance;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ exports.mean = function(data, len) {
return exports.aggNums(function(a, b) { return a + b; }, 0, data) / len;
};

exports.geoMean = function(data, len) {
exports.geometricMean = function(data, len) {
if(!len) len = exports.len(data);
return exports.aggNums(function(a, b) { return a * b; }, 0, data) ** (1 / len);
}
return Math.pow(exports.aggNums(function(a, b) { return a * b; }, 1, data), 1 / len);
};

exports.midRange = function(numArr) {
if(numArr === undefined || numArr.length === 0) return undefined;
Expand Down
4 changes: 2 additions & 2 deletions src/plots/cartesian/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ module.exports = {
'max ascending', 'max descending',
'sum ascending', 'sum descending',
'mean ascending', 'mean descending',
'geomean ascending', 'geomean descending',
'geometric mean ascending', 'geometric mean descending',
'median ascending', 'median descending'
],
dflt: 'trace',
Expand All @@ -1027,7 +1027,7 @@ module.exports = {
'the *trace* mode. The unspecified categories will follow the categories in `categoryarray`.',
'Set `categoryorder` to *total ascending* or *total descending* if order should be determined by the',
'numerical order of the values.',
'Similarly, the order can be determined by the min, max, sum, mean, geomean or median of all the values.'
'Similarly, the order can be determined by the min, max, sum, mean, geometric mean or median of all the values.'
].join(' ')
},
categoryarray: {
Expand Down
4 changes: 2 additions & 2 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -3092,7 +3092,7 @@ plots.doCalcdata = function(gd, traces) {
Registry.getComponentMethod('errorbars', 'calc')(gd);
};

var sortAxisCategoriesByValueRegex = /(total|sum|min|max|mean|median) (ascending|descending)/;
var sortAxisCategoriesByValueRegex = /(total|sum|min|max|mean|geometric mean|median) (ascending|descending)/;

function sortAxisCategoriesByValue(axList, gd) {
var affectedTraces = [];
Expand Down Expand Up @@ -3127,7 +3127,7 @@ function sortAxisCategoriesByValue(axList, gd) {
'sum': function(values) {return Lib.aggNums(function(a, b) { return a + b;}, null, values);},
'total': function(values) {return Lib.aggNums(function(a, b) { return a + b;}, null, values);},
'mean': function(values) {return Lib.mean(values);},
'geomean': function(values) {return Lib.geoMean(values);},
'geometric mean': function(values) {return Lib.geometricMean(values);},
'median': function(values) {return Lib.median(values);}
};

Expand Down
10 changes: 5 additions & 5 deletions test/jasmine/tests/calcdata_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1154,19 +1154,19 @@ describe('calculated data and points', function() {
checkAggregatedValue(baseMock, expectedAgg, false, done);
});

it('takes the geomean of all values per category across traces of type ' + trace.type, function(done) {
it('takes the geometric mean of all values per category across traces of type ' + trace.type, function(done) {
var type = trace.type;
var data = [7, 2, 3];
var data2 = [5, 4, 2];
var baseMock = { data: [makeData(type, axName, cat, data), makeData(type, axName, cat, data2)], layout: {}};
baseMock.layout[axName] = { type: 'category', categoryorder: 'geomean ascending'};
baseMock.layout[axName] = { type: 'category', categoryorder: 'geometric mean ascending'};

var expectedAgg = [['a', Math.sqrt(data[0] * data2[0])], ['b', Math.sqrt(data[1] * data2[1])], ['c', Math.sqrt(data[2] * data2[2])]];
// TODO: how to actually calc these? what do these even mean?
if(type === 'histogram') expectedAgg = [['a', 2], ['b', 1], ['c', 1]];
if(type === 'histogram2d') expectedAgg = [['a', 2 / 3], ['b', 1 / 3], ['c', 1 / 3]];
if(type === 'contour' || type === 'heatmap') expectedAgg = [['a', expectedAgg[0][1] / 3], ['b', expectedAgg[1][1] / 3], ['c', expectedAgg[2][1] / 3]];
if(type === 'histogram2dcontour') expectedAgg = [['a', 2 / 4], ['b', 1 / 4], ['c', 1 / 4]];
if(type === 'histogram2d') expectedAgg = [['a', 0], ['b', 0], ['c', 0]];
if(type === 'contour' || type === 'heatmap') expectedAgg = [['a', 0], ['b', 0], ['c', 0]];
if(type === 'histogram2dcontour') expectedAgg = [['a', 0], ['b', 0], ['c', 0]];

checkAggregatedValue(baseMock, expectedAgg, false, done);
});
Expand Down
8 changes: 4 additions & 4 deletions test/jasmine/tests/lib_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,20 @@ describe('Test lib.js:', function() {
});
});

describe('geomean() should', function() {
describe('geometricMean() should', function() {
it('toss out non-numerics (strings)', function() {
var input = [1, 2, 'apple', 'orange'];
var res = Lib.geomean(input);
var res = Lib.geometricMean(input);
expect(res).toBeCloseTo(1.414, 3);
});
it('toss out non-numerics (NaN)', function() {
var input = [1, 2, NaN];
var res = Lib.geomean(input);
var res = Lib.geometricMean(input);
expect(res).toBeCloseTo(1.414, 3);
});
it('evaluate numbers which are passed around as text strings:', function() {
var input = ['1', '2'];
var res = Lib.geomean(input);
var res = Lib.geometricMean(input);
expect(res).toBeCloseTo(1.414, 3);
});
});
Expand Down

0 comments on commit 447021b

Please sign in to comment.