From dfbaad1895dd4380040b1f3957f5d2ba6d4a0eda Mon Sep 17 00:00:00 2001 From: prabhathc <17132210+prabhathc@users.noreply.github.com> Date: Sun, 12 Jun 2022 20:22:31 -0400 Subject: [PATCH 1/9] feature(geomean): added geomean function + upkeep --- src/lib/index.js | 1 + src/lib/stats.js | 5 +++++ src/plots/cartesian/layout_attributes.js | 3 ++- src/plots/plots.js | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/index.js b/src/lib/index.js index 5d97f2cfc89..413859b70fd 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -114,6 +114,7 @@ var statsModule = require('./stats'); lib.aggNums = statsModule.aggNums; lib.len = statsModule.len; lib.mean = statsModule.mean; +lib.geoMean = statsModule.geoMean; lib.median = statsModule.median; lib.midRange = statsModule.midRange; lib.variance = statsModule.variance; diff --git a/src/lib/stats.js b/src/lib/stats.js index 2f2350dfcf9..463f3960855 100644 --- a/src/lib/stats.js +++ b/src/lib/stats.js @@ -47,6 +47,11 @@ exports.mean = function(data, len) { return exports.aggNums(function(a, b) { return a + b; }, 0, data) / len; }; +exports.geoMean = function(data, len) { + if(!len) len = exports.len(data); + return exports.aggNums(function(a, b) { return a * b; }, 0, data) ** (1 / len); +} + exports.midRange = function(numArr) { if(numArr === undefined || numArr.length === 0) return undefined; return (exports.aggNums(Math.max, null, numArr) + exports.aggNums(Math.min, null, numArr)) / 2; diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index a693fb4cb76..cfc48b79028 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -1012,6 +1012,7 @@ module.exports = { 'max ascending', 'max descending', 'sum ascending', 'sum descending', 'mean ascending', 'mean descending', + 'geomean ascending', 'geomean descending', 'median ascending', 'median descending' ], dflt: 'trace', @@ -1026,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 or median of all the values.' + 'Similarly, the order can be determined by the min, max, sum, mean, geomean or median of all the values.' ].join(' ') }, categoryarray: { diff --git a/src/plots/plots.js b/src/plots/plots.js index cda76cf8f37..e90b8c4fc49 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -3127,6 +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)}, 'median': function(values) {return Lib.median(values);} }; From e8d3fff9cfb9e84d63a8c40f841502a1765fac63 Mon Sep 17 00:00:00 2001 From: prabhathc <17132210+prabhathc@users.noreply.github.com> Date: Sun, 12 Jun 2022 20:47:08 -0400 Subject: [PATCH 2/9] feature(geomean): add draftlog --- draftlogs/6223_add.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 draftlogs/6223_add.md diff --git a/draftlogs/6223_add.md b/draftlogs/6223_add.md new file mode 100644 index 00000000000..5743ef0c1ff --- /dev/null +++ b/draftlogs/6223_add.md @@ -0,0 +1 @@ + - Add geomean functionality and 'geomean ascending' + 'geomean descending' to `category_order` on cartesian axes [[#6223](https://github.com/plotly/plotly.js/pull/6223)] \ No newline at end of file From b175c9cd2cd331bf0150f70a709b3a663b21ce17 Mon Sep 17 00:00:00 2001 From: acxz <17132214+acxz@users.noreply.github.com> Date: Sun, 12 Jun 2022 20:37:18 -0400 Subject: [PATCH 3/9] add geomean test --- test/jasmine/tests/calcdata_test.js | 17 +++++++++++++++++ test/jasmine/tests/lib_test.js | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 801aaa96acd..2bb185fca05 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -1154,6 +1154,23 @@ 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) { + 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'}; + + 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]]; + + checkAggregatedValue(baseMock, expectedAgg, false, done); + }); + it('takes the median of all values per category across traces of type ' + trace.type, function(done) { var type = trace.type; var data = [7, 2, 3]; diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index 647c9c4d5b9..bae5f206192 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -126,6 +126,24 @@ describe('Test lib.js:', function() { }); }); + describe('geomean() should', function() { + it('toss out non-numerics (strings)', function() { + var input = [1, 2, 'apple', 'orange']; + var res = Lib.geomean(input); + expect(res).toBeCloseTo(1.414, 3); + }); + it('toss out non-numerics (NaN)', function() { + var input = [1, 2, NaN]; + var res = Lib.geomean(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); + expect(res).toBeCloseTo(1.414, 3); + }); + }); + describe('midRange() should', function() { it('should calculate the arithmetic mean of the maximum and minimum value of a given array', function() { var input = [1, 5.5, 6, 15, 10, 13]; From 794aba9c326cd3a60e633b9ede595682cf161a22 Mon Sep 17 00:00:00 2001 From: Akash Patel <17132214+acxz@users.noreply.github.com> Date: Sun, 12 Jun 2022 21:15:21 -0400 Subject: [PATCH 4/9] Update src/plots/plots.js --- src/plots/plots.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index e90b8c4fc49..84b3e3ab7f4 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -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)}, + 'geomean': function(values) {return Lib.geoMean(values);}, 'median': function(values) {return Lib.median(values);} }; From 9da8b0745a23e38979a21ffa4dbf8a7c6038346c Mon Sep 17 00:00:00 2001 From: acxz <17132214+acxz@users.noreply.github.com> Date: Sat, 18 Jun 2022 12:47:39 -0400 Subject: [PATCH 5/9] add attribution --- draftlogs/6223_add.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/draftlogs/6223_add.md b/draftlogs/6223_add.md index 5743ef0c1ff..c4853f7f97c 100644 --- a/draftlogs/6223_add.md +++ b/draftlogs/6223_add.md @@ -1 +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)] \ No newline at end of file + - Add geomean functionality and 'geomean ascending' + 'geomean 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! From 447021b30f3c72e436cec957bf810be3cf3aa7ac Mon Sep 17 00:00:00 2001 From: acxz <17132214+acxz@users.noreply.github.com> Date: Sat, 18 Jun 2022 12:57:57 -0400 Subject: [PATCH 6/9] replace geomean with geometric mean or geometricMean fix geometricMean computation --- draftlogs/6223_add.md | 2 +- src/lib/index.js | 2 +- src/lib/stats.js | 6 +++--- src/plots/cartesian/layout_attributes.js | 4 ++-- src/plots/plots.js | 4 ++-- test/jasmine/tests/calcdata_test.js | 10 +++++----- test/jasmine/tests/lib_test.js | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/draftlogs/6223_add.md b/draftlogs/6223_add.md index c4853f7f97c..d90cd7d103a 100644 --- a/draftlogs/6223_add.md +++ b/draftlogs/6223_add.md @@ -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! diff --git a/src/lib/index.js b/src/lib/index.js index 413859b70fd..af997e0236f 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -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; diff --git a/src/lib/stats.js b/src/lib/stats.js index 463f3960855..0ffbf4eb0e9 100644 --- a/src/lib/stats.js +++ b/src/lib/stats.js @@ -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; diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index cfc48b79028..1c1be7bd347 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -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', @@ -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: { diff --git a/src/plots/plots.js b/src/plots/plots.js index 84b3e3ab7f4..ace7589c2a0 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -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 = []; @@ -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);} }; diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 2bb185fca05..517a583f576 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -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); }); diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index bae5f206192..cc09b4c49c9 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -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); }); }); From 4f7663b18a2b8448f898db2263a0287d415dae3b Mon Sep 17 00:00:00 2001 From: "Patel, Akash M" Date: Thu, 11 Jul 2024 21:28:18 -0500 Subject: [PATCH 7/9] change name of geometric_mean aggFn --- src/plots/plots.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index 55469c69b7f..ab48ea34915 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -3223,7 +3223,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);}, - geometric_mean: function(values) {return Lib.geometricMean(values);}, + 'geometric mean': function(values) {return Lib.geometricMean(values);}, median: function(values) {return Lib.median(values);} }; From e04e6528f8012d9b4b62762deddfd7300e7414ac Mon Sep 17 00:00:00 2001 From: Akash Patel <17132214+acxz@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:56:22 -0500 Subject: [PATCH 8/9] skip `ohlc` and `candlestick` which fail with tiny tolerance Co-authored-by: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com> --- test/jasmine/tests/calcdata_test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jasmine/tests/calcdata_test.js b/test/jasmine/tests/calcdata_test.js index 2ac341d8582..86ef265c7b4 100644 --- a/test/jasmine/tests/calcdata_test.js +++ b/test/jasmine/tests/calcdata_test.js @@ -1161,6 +1161,8 @@ describe('calculated data and points', function() { }); it('takes the geometric mean of all values per category across traces of type ' + trace.type, function(done) { + if(trace.type === 'ohlc' || trace.type === 'candlestick') return done(); + var type = trace.type; var data = [7, 2, 3]; var data2 = [5, 4, 2]; From 5597352750ac2403d87a2240ef3e7a7995d883be Mon Sep 17 00:00:00 2001 From: "Patel, Akash M" Date: Sun, 14 Jul 2024 14:29:06 -0500 Subject: [PATCH 9/9] update plot-schema diff --- test/plot-schema.json | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/test/plot-schema.json b/test/plot-schema.json index 929904f8d9a..6821a47fabc 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -4869,7 +4869,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "calc", "valType": "enumerated", @@ -4888,6 +4888,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -5653,7 +5655,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "calc", "valType": "enumerated", @@ -5672,6 +5674,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -7170,7 +7174,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "plot", "valType": "enumerated", @@ -7189,6 +7193,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -8002,7 +8008,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "plot", "valType": "enumerated", @@ -8021,6 +8027,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -8834,7 +8842,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "plot", "valType": "enumerated", @@ -8853,6 +8861,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -14011,7 +14021,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "calc", "valType": "enumerated", @@ -14030,6 +14040,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ] @@ -15660,7 +15672,7 @@ "valType": "string" }, "categoryorder": { - "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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 or median of all the values.", + "description": "Specifies the ordering logic for the case of categorical variables. By default, plotly uses *trace*, which specifies the order that is present in the data supplied. Set `categoryorder` to *category ascending* or *category descending* if order should be determined by the alphanumerical order of the category names. Set `categoryorder` to *array* to derive the ordering from the attribute `categoryarray`. If a category is not found in the `categoryarray` array, the sorting behavior for that attribute will be identical to 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, geometric mean or median of all the values.", "dflt": "trace", "editType": "calc", "valType": "enumerated", @@ -15679,6 +15691,8 @@ "sum descending", "mean ascending", "mean descending", + "geometric mean ascending", + "geometric mean descending", "median ascending", "median descending" ]