Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a18dc43

Browse filesBrowse files
committed
sort categories by value: support different aggregation functions
1 parent 6939d13 commit a18dc43
Copy full SHA for a18dc43

File tree

Expand file treeCollapse file tree

4 files changed

+74
-25
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+74
-25
lines changed

‎src/plots/cartesian/layout_attributes.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/layout_attributes.js
+5-2Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,11 @@ module.exports = {
817817
categoryorder: {
818818
valType: 'enumerated',
819819
values: [
820-
'trace', 'category ascending', 'category descending', 'array', 'value ascending', 'value descending'
821-
/* , 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later
820+
'trace', 'category ascending', 'category descending', 'array',
821+
'value ascending', 'value descending',
822+
'min ascending', 'min descending',
823+
'max ascending', 'max descending',
824+
'sum ascending', 'sum descending'
822825
],
823826
dflt: 'trace',
824827
role: 'info',

‎src/plots/plots.js

Copy file name to clipboardExpand all lines: src/plots/plots.js
+44-18Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2844,59 +2844,85 @@ plots.doCalcdata = function(gd, traces) {
28442844
doCrossTraceCalc(gd);
28452845

28462846
// Sort axis categories per value if specified
2847-
if(sortAxisCategoriesByValue(axList, gd)) {
2847+
var sorted = sortAxisCategoriesByValue(axList, gd);
2848+
if(sorted.length) {
28482849
// If a sort operation was performed, run calc() again
2849-
for(i = 0; i < fullData.length; i++) calci(i, true);
2850-
for(i = 0; i < fullData.length; i++) calci(i, false);
2850+
for(i = 0; i < sorted.length; i++) calci(sorted[i], true);
2851+
for(i = 0; i < sorted.length; i++) calci(sorted[i], false);
28512852
doCrossTraceCalc(gd);
28522853
}
28532854

28542855
Registry.getComponentMethod('fx', 'calc')(gd);
28552856
Registry.getComponentMethod('errorbars', 'calc')(gd);
28562857
};
28572858

2859+
var sortAxisCategoriesByValueRegex = /(value|sum|min|max) (ascending|descending)/;
2860+
28582861
function sortAxisCategoriesByValue(axList, gd) {
2859-
var sortByValue = false;
2862+
var sortByValue = [];
28602863
var i, j, k;
28612864
for(i = 0; i < axList.length; i++) {
28622865
var ax = axList[i];
28632866
if(ax.type !== 'category') continue;
28642867

28652868
// Order by value
2866-
if(ax.categoryorder === 'value ascending' ||
2867-
ax.categoryorder === 'value descending') {
2868-
sortByValue = true;
2869-
2870-
// Store value associated with each category
2869+
var m = ax.categoryorder.match(sortAxisCategoriesByValueRegex);
2870+
if(m) {
2871+
// Store values associated with each category
28712872
var categoriesValue = [];
28722873
for(j = 0; j < ax._categories.length; j++) {
2873-
categoriesValue.push([ax._categories[j], 0]);
2874+
categoriesValue.push([ax._categories[j], []]);
28742875
}
28752876

2876-
// Aggregate values across traces
2877+
// Collect values across traces
28772878
for(j = 0; j < ax._traceIndices.length; j++) {
2879+
// Keep track of traces we sort!
28782880
var traceIndex = ax._traceIndices[j];
2881+
sortByValue.push(traceIndex);
2882+
28792883
var fullData = gd._fullData[traceIndex];
28802884
if(fullData.visible !== true) continue;
2881-
var cd = gd.calcdata[traceIndex];
2882-
var type = fullData.type;
28832885

2886+
var type = fullData.type;
28842887
if(type === 'histogram') delete fullData._autoBinFinished;
28852888

2889+
var cd = gd.calcdata[traceIndex];
28862890
for(k = 0; k < cd.length; k++) {
2891+
var cat, value;
28872892
if(type === 'scatter') {
28882893
if(ax._id[0] === 'x') {
2889-
categoriesValue[cd[k].x][1] += cd[k].y;
2894+
cat = cd[k].x;
2895+
value = cd[k].y;
28902896
} else if(ax._id[0] === 'y') {
2891-
categoriesValue[cd[k].y][1] += cd[k].x;
2897+
cat = cd[k].y;
2898+
value = cd[k].x;
28922899
}
28932900
} else if(type === 'histogram') {
2894-
categoriesValue[cd[k].p][1] += cd[k].s;
2901+
cat = cd[k].p;
2902+
value = cd[k].s;
28952903
}
2904+
categoriesValue[cat][1].push(value);
28962905
}
28972906
}
28982907

2899-
// Sort by value
2908+
// Aggregate values
2909+
var aggFn;
2910+
switch(m[1]) {
2911+
case 'min':
2912+
aggFn = Math.min;
2913+
break;
2914+
case 'max':
2915+
aggFn = Math.max;
2916+
break;
2917+
default:
2918+
aggFn = function(a, b) { return a + b;};
2919+
}
2920+
2921+
for(j = 0; j < categoriesValue.length; j++) {
2922+
categoriesValue[j][1] = Lib.aggNums(aggFn, null, categoriesValue[j][1]);
2923+
}
2924+
2925+
// Sort by aggregated value
29002926
categoriesValue.sort(function(a, b) {
29012927
return a[1] - b[1];
29022928
});
@@ -2907,7 +2933,7 @@ function sortAxisCategoriesByValue(axList, gd) {
29072933
});
29082934

29092935
// Reverse if descending
2910-
if(ax.categoryorder === 'value descending') {
2936+
if(m[2] === 'descending') {
29112937
ax._initialCategories.reverse();
29122938
}
29132939

Loading

‎test/image/mocks/hist_category_value_ascending.json

Copy file name to clipboardExpand all lines: test/image/mocks/hist_category_value_ascending.json
+25-5Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,38 @@
11
{
22
"data": [{
3-
"x": ["a", "b", "c", "a", "b", "d", "b", "c"],
3+
"x": ["a", "b", "c", "a", "b", "d", "b", "c", "b", "b"],
44
"type": "histogram"
55
},
66
{
7-
"x": ["d", "c", "b", "a", "e", "a", "b"],
7+
"x": ["d", "c", "a", "e", "a"],
88
"type": "histogram"
9+
},
10+
{
11+
"y": ["a", "b", "c", "a", "b", "d", "b", "c"],
12+
"type": "histogram",
13+
"xaxis": "x2",
14+
"yaxis": "y2"
15+
},
16+
{
17+
"y": ["d", "c", "b", "a", "e", "a", "b"],
18+
"type": "histogram",
19+
"xaxis": "x2",
20+
"yaxis": "y2"
921
}],
1022
"layout": {
11-
"title": "xaxis.categoryorder: \"value ascending\"",
12-
"height": 300,
13-
"width": 400,
23+
"title": "categoryorder: \"value ascending\"",
24+
"height": 400,
25+
"width": 600,
1426
"barmode": "stack",
1527
"xaxis": {
28+
"domain": [0, 0.45],
29+
"categoryorder": "value ascending"
30+
},
31+
"xaxis2": {
32+
"domain": [0.55, 1]
33+
},
34+
"yaxis2": {
35+
"anchor": "x2",
1636
"categoryorder": "value ascending"
1737
}
1838
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.