Categorical Plots and Coloring
VisiData automatically assigns distinct colors to each value of a categorical key column on the canvas. This turns a monochrome scatterplot into a group-aware visualization — no configuration needed.
The pattern: mark a categorical column as key, mark a numeric column as key, then press . on a second numeric column. VisiData colors each dot by category. This reveals group-level patterns that a plain scatterplot hides.
Sample Data Used in This Lesson
cat > ~/github/practice-folder/visidata/09-metrics/service-latency.csv << 'EOF'
service,region,requests,latency_ms,error_rate
auth,SG,8200,45,0.02
auth,KL,4100,62,0.03
auth,JK,2300,88,0.08
api,SG,32000,120,0.01
api,KL,18000,145,0.02
api,JK,9500,198,0.05
cache,SG,55000,8,0.00
cache,KL,31000,12,0.00
cache,JK,15000,18,0.01
db,SG,12000,85,0.01
db,KL,7200,102,0.02
db,JK,3100,145,0.06
EOF
vd ~/github/practice-folder/visidata/09-metrics/service-latency.csv
Concept: How Categorical Coloring Works
When you mark:
- A categorical column as key → VisiData assigns one color per distinct value
- A numeric column as key → used as the x-axis
- Press
.on a numeric column → that column becomes the y-axis
Result: each point on the canvas is colored by the categorical key.
Example 1 — Color by Service Type
Goal: See if different services have different latency characteristics.
# Step 1: Cast numeric columns
# Move to 'requests' → #
# Move to 'latency_ms' → #
# Move to 'error_rate' → %
# Step 2: Set categorical key (color dimension)
# Move to 'service' column
! # categorical key → 4 colors (auth, api, cache, db)
# Step 3: Set numeric x-axis key
# Move to 'requests' column
! # x-axis: request volume
# Step 4: Plot latency_ms on y-axis
# Move to 'latency_ms' column
. # canvas opens
Canvas (schematic):
latency_ms
│
200│ ◆ ◆ ← db and api (high latency, moderate volume)
180│ ◆
160│
140│ ▲ ← auth (moderate latency)
120│ ■ ← api-SG (high volume, moderate latency)
100│
80│ ▲
60│ ▲
40│
20│ ● ● ← cache (low latency, very high volume)
10│ ●
0│
└──────────────────────────────
2K 8K 15K 32K 55K
requests
Pattern visible: cache cluster bottom-right (low latency, high volume). db cluster top-left (high latency, low volume). api scattered in middle.
Example 2 — Color by Region
Goal: See if the same service performs differently across regions.
# Remove the 'service' key (z! on service column)
z!
# Set 'region' as categorical key
# Move to 'region' column
! # 3 colors: SG, KL, JK
# Keep 'requests' as numeric x-axis key
# Move to 'latency_ms' column
.
Pattern: JK points consistently higher on the y-axis (higher latency) — regional infrastructure difference visible.
Example 3 — Bar Chart per Category
For a count-based view of how each service distributes across regions:
# Return to source sheet: q
# Move to 'service' column
Shift+F # frequency table: count per service
# Now move to 'count' column
! # set count as key (x-axis)
# Move to the 'service' column in the frequency table
. # bar chart: one bar per service
Result: horizontal bars showing request volume per service type.
Example 4 — Error Rate vs Latency, Colored by Service
Goal: Find which services have both high latency AND high error rates.
# Return to source: q (multiple times to get back)
vd ~/github/practice-folder/visidata/09-metrics/service-latency.csv
# Cast columns
# latency_ms → #
# error_rate → %
# Set service as categorical key
# Move to 'service' → !
# Set latency_ms as numeric x-axis key
# Move to 'latency_ms' → !
# Plot error_rate on y-axis
# Move to 'error_rate' → .
Pattern: db-JK and auth-JK points appear top-right — worst performers. cache-* points cluster bottom-left — best performers across all regions.
Reading a Multi-Color Canvas
● ■ ◆ ▲ each shape/color = one category value
· ⠿ ⣿ density indicators (more points in same cell)
axis labels numeric scale
legend category → color mapping (shown on right if terminal wide enough)
The actual characters depend on your terminal's braille/block support. More ⣿ = more overlapping data points.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| All points same color | No categorical key set | Mark a text column as key with ! |
| Too many colors, hard to distinguish | Categorical column has too many distinct values | Filter to top N categories first |
| Points cluster at x=0 | Numeric x-axis column not cast | Cast to # or % before setting as key |
| Canvas shows only one point | All rows have same x-value | Use a more granular x-axis column |
| Colors not rendering | Terminal doesn't support 256 colors | Add export TERM=xterm-256color to .bashrc |
Full Workflow Template
vd data.csv
1. Cast numeric columns: #, %, @
2. Mark categorical column as key: ! on text column
3. Mark numeric x-axis as key: ! on numeric column
4. Move to y-axis column: .
5. Toggle layers: 1–9 to show/hide category groups
6. Zoom: + / - / _
7. Focus region: x to set x-axis range
8. Drill down: Enter on a cluster → source rows for that group
9. Press q → back to canvas, q → back to source
Hands-On Practice
vd ~/github/practice-folder/visidata/09-metrics/service-latency.csv
# 1. Cast requests (#), latency_ms (#), error_rate (%)
# 2. Mark 'service' as categorical key (!)
# 3. Mark 'requests' as numeric x-axis key (!)
# 4. Move to 'latency_ms' → press . → see colored scatterplot
# 5. Use + to zoom, h/l to pan
# 6. Press Enter on a cluster → inspect source rows
# 7. Press q twice → back to source
# 8. Remove service key (z!), mark 'region' as key (!)
# 9. Press . on latency_ms → compare regions
# 10. Move to 'error_rate' → . → error rate by region