Skip to main content

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.

Learning Focus

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:

  1. A categorical column as key → VisiData assigns one color per distinct value
  2. A numeric column as key → used as the x-axis
  3. 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

ProblemCauseFix
All points same colorNo categorical key setMark a text column as key with !
Too many colors, hard to distinguishCategorical column has too many distinct valuesFilter to top N categories first
Points cluster at x=0Numeric x-axis column not castCast to # or % before setting as key
Canvas shows only one pointAll rows have same x-valueUse a more granular x-axis column
Colors not renderingTerminal doesn't support 256 colorsAdd 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

What's Next