Preserving Categorical Data Order
This example demonstrates how to preserve the order of categorical data when creating charts. By default, Observable Plot sorts categorical values alphabetically, but you can override this behavior using explicit domain specification.
Problem: Alphabetical Sorting
Workflow Status Example (Wrong Order)
Without specifying a domain, the categories will be sorted alphabetically:
View Source
data:
source: [
{"status": "todo", "count": 12, "priority": "normal"},
{"status": "in-progress", "count": 8, "priority": "normal"},
{"status": "done", "count": 25, "priority": "normal"}
]
type: bar
x: status
y: count
title: "Task Status (Alphabetically Sorted - Wrong Order)"
fill: steelblue
height: 300Result: Categories appear as "done", "in-progress", "todo" ❌
This breaks the natural workflow progression!
Solution: Explicit Domain
Workflow Status Example (Correct Order)
Specify the domain to preserve the intended order:
View Source
data:
source: [
{"status": "todo", "count": 12, "priority": "normal"},
{"status": "in-progress", "count": 8, "priority": "normal"},
{"status": "done", "count": 25, "priority": "normal"}
]
type: bar
x: status
y: count
scales:
x:
domain: ["todo", "in-progress", "done"]
title: "Task Status (Correct Workflow Order)"
fill: orange
height: 300Result: Categories appear as "todo", "in-progress", "done" ✓
Perfect! The workflow progression makes sense.
Common Use Cases
Time Periods (Quarters)
View Source
data:
source: [
{"quarter": "Q1", "revenue": 125000},
{"quarter": "Q2", "revenue": 145000},
{"quarter": "Q3", "revenue": 135000},
{"quarter": "Q4", "revenue": 165000}
]
type: bar
x: quarter
y: revenue
scales:
x:
domain: ["Q1", "Q2", "Q3", "Q4"]
title: "Quarterly Revenue (Correct Temporal Order)"
fill: teal
height: 300Priority Levels
View Source
data:
source: [
{"priority": "P0", "count": 3},
{"priority": "P1", "count": 8},
{"priority": "P2", "count": 15},
{"priority": "P3", "count": 22}
]
type: bar
x: priority
y: count
scales:
x:
domain: ["P0", "P1", "P2", "P3"]
title: "Issues by Priority Level"
fill: crimson
height: 300Ordinal Rankings
View Source
data:
source: [
{"severity": "low", "incidents": 45},
{"severity": "medium", "incidents": 28},
{"severity": "high", "incidents": 12},
{"severity": "critical", "incidents": 3}
]
type: bar
x: severity
y: incidents
scales:
x:
domain: ["low", "medium", "high", "critical"]
title: "Security Incidents by Severity"
fill: purple
height: 300Multi-Mark Charts
For multi-mark charts, set the domain at the top-level scales:
View Source
data:
source: [
{"month": "Jan", "target": 100, "actual": 95},
{"month": "Feb", "target": 110, "actual": 108},
{"month": "Mar", "target": 105, "actual": 112},
{"month": "Apr", "target": 115, "actual": 118}
]
scales:
x:
domain: ["Jan", "Feb", "Mar", "Apr"]
marks:
- type: bar
x: month
y: actual
fill: lightblue
- type: line
x: month
y: target
stroke: red
strokeWidth: 2
marker: dot
title: "Monthly Performance: Target vs Actual"
height: 350Advanced: Using Object-Based Axis Configuration
You can also set the domain directly in the axis configuration:
View Source
data:
source: [
{"stage": "backlog", "items": 42},
{"stage": "planning", "items": 15},
{"stage": "development", "items": 23},
{"stage": "testing", "items": 8},
{"stage": "deployed", "items": 67}
]
type: bar
x:
field: stage
type: band
domain: ["backlog", "planning", "development", "testing", "deployed"]
label: "Development Stage"
y: items
title: "Items by Development Stage"
fill: mediumseagreen
height: 350Line Charts with Categorical X-Axis
The same principle applies to line charts:
View Source
data:
source: [
{"phase": "alpha", "users": 50},
{"phase": "beta", "users": 250},
{"phase": "rc", "users": 800},
{"phase": "ga", "users": 5000}
]
type: line
x: phase
y: users
scales:
x:
domain: ["alpha", "beta", "rc", "ga"]
title: "User Growth Through Release Phases"
stroke: darkblue
strokeWidth: 3
marker: dot
height: 350Key Takeaways
- Default Behavior: Observable Plot sorts categorical data alphabetically
- Use
scales.x.domainorscales.y.domainto preserve your intended order - Common scenarios:
- Workflow stages (todo → in-progress → done)
- Time periods (Q1 → Q2 → Q3 → Q4)
- Rankings (low → medium → high)
- Release phases (alpha → beta → rc → ga)
- Multi-mark charts: Set domain at top-level
scalesconfiguration - Object-based axes: Set domain directly in axis configuration
Related Examples
- Scales Reference - Scale configuration options
- Chart Gallery - Complete chart examples