Skip to content

[feat]: --col-axis flag for multi-column competitor charts on a single axis #220

Description

@fahimfaisaal

Problem / use case

With grouped CSV/JSON, every numeric column becomes its own stat type, and the UI creates one chart per stat.

For wide “competitor” tables (e.g. framework benchmarks), columns are series of the same metric, not separate charts. Example (concurrency.csv):

load,default,chi,echo,gin,goframe,httpz
100,3103.62,3103.73,...
1000,32423.67,32421.28,...
vizb bar concurrency.csv -g load -p y -o out.html

Today this yields 6 independent charts (one per framework). The desired shape is one chart where frameworks share an axis — same idea as merge’s --tag-axis / -A placing tags on n/x/y/z instead of splitting views.

Proposed solution

Flag

Flag Short Values Default
--col-axis -A n, x, y, z unset (current multi-chart behavior)

Target UX:

vizb bar concurrency.csv -o out.html -g load -p y -A x
# or long form:
vizb bar concurrency.csv -o out.html -g load -p y --col-axis x
  • load → group dimension y (series / variants)
  • numeric column namesx categories
  • all values share a single stat → one chart

Naming: --col-axis (“put column names on this axis”), parallel to merge’s --tag-axis. Avoids --stat-axis because --stat already means the analytics panel.

Data transform

After parse + aggregate, when --col-axis is set, expand multi-stat points into long form:

Before (-g load -p y):

{ "yAxis": "100", "stats": [
  { "type": "default", "value": 3103.62 },
  { "type": "chi", "value": 3103.73 }
]}

After (-A x / --col-axis x):

{ "yAxis": "100", "xAxis": "default", "stats": [{ "value": 3103.62 }] }
{ "yAxis": "100", "xAxis": "chi",     "stats": [{ "value": 3103.73 }] }

Rules:

  1. One output point per (input point × stat).
  2. Write the column label onto the chosen dimension (Name / XAxis / YAxis / ZAxis).
  3. Replace Stats with a single stat: Type left empty so JSON omits type (json:"type,omitempty" on shared.Stat). Wire format has no type key → UI sees undefined. Same Value.
  4. Ensure Dataset.Axes includes the inject axis (reuse merge’s ensureInjectAxis pattern).

Chart title (UI)

Empty/omitted stats[].type still yields one chart signature. The card header must not stay blank:

  • When type is empty/undefined, show Dataset.Name (from -n / default "Comparisons") as the chart title.
  • Accept that the dataset name may also appear elsewhere in the UI.

Validation

Condition Behavior
--col-axis without group warn + skip — flag ignored; multi-chart default unchanged
--col-axis with non-csv/json warn + skip
Solo --select / value / mixed (no grouped multi-column stats) warn + skip
Same axis as group (e.g. -g load -p x -A x) fatal error + exit
-A z without both x and y present after grouping fatal error + exit
Only one numeric column allowed (expand still produces one chart)

Same-axis conflict must fail hard (do not overwrite or append like merge tag injection):

vizb bar concurrency.csv -g load -p x -A x -o out.html
# Error: --col-axis "x" conflicts with group dimension (already used by --group-pattern)

Implementation sketch

Layer Change
cmd/cli/dataflags.go Add col-axis / -A to DataFlags
pkg/parser/registry.go Config.ColAxis string
cmd/cli/flagbag.go Map flag → cfg.ColAxis in ParseConfig
shared/expand.go ExpandStatsOntoAxis(points, dim Dimension) []DataPoint + tests
shared/dataset.go Stat.Typejson:"type,omitempty"
shared/merge.go Export axis-ensure helper for dataset assembly
cmd/cli/pipeline.go After aggregate: validate + expand when ColAxis set; ensure inject axis in buildDataset
UI Empty type → chart title falls back to Dataset.Name
Docs Group guide: competitor / wide-table example

Aggregation stays before expand so duplicate rows still sum per column first.

Acceptance / verification

# One chart: frameworks on X, load on Y series
vizb bar concurrency.csv -g load -p y -A x -n "HTTP frameworks" -o /tmp/comp.json
# assert: stats have no type key, xAxis in {default,chi,...}, yAxis in {100,1000,5000}
# HTML: chart card title shows "HTTP frameworks"

# Classic grouped bar: load on X, frameworks as Y series
vizb bar concurrency.csv -g load -p x -A y -o /tmp/comp2.html

# Same axis as group → fatal exit
vizb bar concurrency.csv -g load -p x -A x -o /tmp/bad.html

# No group → warn + skip
vizb bar concurrency.csv -A x -o /tmp/skip.json

Out of scope

  • Changing default multi-chart behavior without the flag
  • UI-side “merge stats into series” without reshape
  • Auto-detecting competitor tables (all-numeric wide files still need explicit -g + -A)
  • Renaming merge’s -A or sharing one flag across merge and chart commands

Metadata

Metadata

Assignees

Labels

cliCommand line interface related tasksenhancementNew feature or request

Fields

Priority

High

Start date

None yet

Target date

None yet

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions