咨询:Plotly.js为何打乱多类别X轴子系列中A1与B2的顺序
I’ve run into this exact problem before—Plotly’s default behavior for multicategory axes can be frustrating when you need to preserve a custom order instead of letting it sort alphabetically. Let’s break down what’s happening and how to fix it.
Why Your A1/B2 Order Is Getting Shuffled
Plotly automatically sorts multicategory axes alphabetically by default. Even though your data specifies ["A1", "B2", "A1", "B2"...] under each main category, Plotly is re-sorting all subcategories across the entire axis. Since "A1" comes before "B2" alphabetically, it’s grouping all A1s first then B2s, which breaks your desired paired order.
The Quick Fix: Enforce Trace Data Order
The simplest way to lock in your exact sequence is to add categoryorder: 'trace' to your x-axis configuration. This tells Plotly to respect the order of categories as they appear directly in your trace data, overriding the default sort.
Updated Code with Fix
Here’s your modified code (the key change is in the xaxis section):
var data = { "data": [ { "type": "bar", "name": "1 day", "text": [ "85%", "79%", "74%", "57%", "55%", "18%", "50%", "4%" ], "x": [ [ "Croissant", "Croissant", "Doughnut: Cinnamon", "Doughnut: Cinnamon", "Doughnut: Glazed", "Doughnut: Glazed", "Bagel: Sesame", "Bagel: Sesame" ], [ "A1 (N=17)", "B2 (N=15)", "A1 (N=18)", "B2 (N=15)", "A1 (N=10)", "B2 (N=11)", "A1 (N=6)", "B2 (N=9)" ] ], "y": [ 0.8470588235294118, 0.7913333333333333, 0.7357142857142858, 0.5746666666666667, 0.55, 0.18, 0.5, 0.03888888888888889 ], "orientation": "v", "textposition": "auto", "marker": { "color": [ "#39C", "#FA0", "#39C", "#FA0", "#39C", "#FA0", "#39C", "#FA0" ] }, "hoverinfo": "x+y", "hoverformat": "0.0%" } ], "layout": { "type": "bar", "orientation": "v", "barmode": "stack", "series": { "type": "bar", "hoverinfo": "x+y", "dataLabels": { "color": "", "size": "", "bold": false } }, "margin": { "l": 80, "r": 200, "t": 0, "b": 95 }, "xaxis": { "type": "multicategory", "autorange": true, "categoryorder": "trace" // This line fixes the order! }, "yaxis": { "tickformat": "0.0%", "rangemode": "tozero", "type": "linear", "autorange": true }, "colorway": [ "#DADADA", "#4DADC7", "#8165A2", "#884119" ], "legendpos": "right", "width": 800, "height": 420, "bargap": 0.2 } }; Plotly.newPlot("bar-chart-1", data);
How This Works
categoryorder: 'trace' tells Plotly to use the exact order of categories from your trace’s x array. So for each main category (like Croissant), it will display the subcategories in the sequence you specified: A1 first, then B2, and repeat that pattern for every main category in your data.
For More Control: Explicit Category Arrays
If you ever need to reorder main categories independently of their appearance in the trace data, you can use categoryorder: 'array' along with a categoryarray that defines the full multicategory hierarchy. For example:
"xaxis": { "type": "multicategory", "autorange": true, "categoryorder": "array", "categoryarray": [ ["Croissant", "Croissant"], ["Bagel: Sesame", "Bagel: Sesame"], // Reordered main category ["Doughnut: Cinnamon", "Doughnut: Cinnamon"], ["Doughnut: Glazed", "Doughnut: Glazed"] ], "subcategoryorder": "array", "subcategoryarray": [ ["A1 (N=17)", "B2 (N=15)"], ["A1 (N=6)", "B2 (N=9)"], ["A1 (N=18)", "B2 (N=15)"], ["A1 (N=10)", "B2 (N=11)"] ] }
This lets you fully customize both main and subcategory order, but for your current use case, categoryorder: 'trace' is the most straightforward solution.
内容的提问来源于stack exchange,提问作者prototype

