Skip to content

Latest commit

 

History

History
485 lines (386 loc) · 46.3 KB

File metadata and controls

485 lines (386 loc) · 46.3 KB

viz

Generate interactive charts & maps from CSV data using plotly. viz smart creates a "neuro-symbolic" dashboard/visual data dictionary, picking appropriate visualizations using the dataset's statistics, frequency distributions, data dictionary & optional LLM metadata inferencing/classification, with automatic geocoding enrichment. Outputs self-contained, interactive HTML or static PNG/SVG/PDF/JPEG/WebP with the viz_static feature. (Gallery)

Table of Contents | Source: src/cmd/viz.rs | 🪄📇🏎️👆🤖🌐🌎

Description | Examples | Usage | Viz Options | Map Options | Geo Options | Choropleth Options | Smart Options | Common Options

Description

Generate charts/maps from CSV data using the plotly charting library.

Produces a self-contained, interactive HTML chart (the plotly.js runtime is embedded, so charts work offline; map basemaps fetch their tiles over the network at view time unless the white-bg style is used). Set the QSV_VIZ_CDN environment variable to load plotly.js from its CDN instead, shrinking the page by ~1.9MB at the cost of needing network access to view it. By default the embedded plotly.js is gzip-compressed (~1.9MB vs ~4.8MB) and inflated in-browser, which requires a browser with DecompressionStream support (Chrome/Edge 80+, Firefox 113+, or Safari 16.4+); set QSV_VIZ_NO_COMPRESS for plain-text, uncompressed HTML that also works on older browsers. Titles and labels are rendered as plain text - LaTeX (e.g. $\alpha$) is not typeset. With a qsv build that includes the viz_static feature, charts can also be exported as static PNG/SVG/PDF/JPEG/WebP images (this requires a Chromium/Firefox browser at runtime - a webdriver is auto-managed by plotly).

The output format is inferred from the --output file extension (.html is the default). Interactive HTML is written to stdout when --output is not given; image formats always require --output. Use --open to view the result in your default browser/viewer.

Progress is shown on stderr by default: a spinner with per-phase status messages (loading statistics, inferring the data dictionary, computing correlations, rendering, etc.). It is auto-hidden when stderr is not a terminal (e.g. piped or redirected). Set the QSV_PROGRESSBAR environment variable to a falsy value (0/false/off) to disable it.

Chart types (subcommands):

smart       Auto-dashboard. Picks an appropriate chart per column from the
            dataset's statistics & frequency distribution (no --x/--y needed).
bar         Bar chart.        --x = category column, --y = value column.
line        Line chart.       --x = x column, --y = y column.
scatter     Scatter plot.     --x = x column, --y = y column.
scatter3d   3D scatter plot.  --x, --y, --z = three numeric columns.
histogram   Distribution.     --x = numeric column to bin.
box         Box plot.         --y = value column, optional --x = group column.
violin      Violin plot: a box plot plus a KDE density curve revealing the
            distribution's shape (modes, shoulders). Same inputs as box
            (--y = value column, optional --x = group column).
pie         Proportions.      --x = label column, optional --y = value column.
funnel      Stage-by-stage drop-off. --x = stage column, optional --y = value
            column (counts stage occurrences when omitted). Stages keep the
            order they first appear in the file, so the rows define the
            pipeline; plotly labels each band with its conversion from the
            previous stage.
heatmap     Color grid. Correlation matrix of numeric columns (default; an
            optional column subset via --cols), or a category x category pivot
            with --x/--y/--z.
contour     2D density contour of two numeric columns (--x and --y), binned
            into a grid (--bins controls the grid resolution).
candlestick Financial OHLC.   --x = date column, plus --ohlc-open/--high/--low/--close.
ohlc        Financial OHLC bars (same inputs as candlestick).
sankey      Flow diagram.     --source, --target, optional --value column.
radar       Polar/radar chart of numeric --cols, optional --series per trace.
treemap     Part-to-whole hierarchy as nested tiles. --cols = 2+ dimension
            columns (levels), optional --value and --agg.
sunburst    Part-to-whole hierarchy as concentric rings (same inputs as
            treemap). Better for deeper hierarchies.
icicle      Part-to-whole hierarchy as stacked bars per level (same inputs as
            treemap). Level-aligned; good for deep, wide hierarchies.
splom       Scatter-plot matrix: every pair of numeric --cols plotted against
            each other in a grid, with each column's distribution on the
            diagonal. Good for spotting correlations across many numeric
            columns at once (default: all numeric columns).
parcats     Parallel categories: ribbons showing how rows flow across the
            categorical --cols (best with 3-4). Complements sankey (which
            takes 2 columns) for higher-dimensional categorical relationships.
map         Geographic point map (or --density heatmap) on tile basemaps.
            Pick the coordinate columns with the lat/lon options below.
geo         Geographic point map on a projection basemap (coastlines/land/
            countries; no tiles, no token). Uses the same lat/lon options
            as `map`, plus --projection. Good for global/country-scale data.
choropleth  Filled-region map: color whole regions (countries, US states, or
            custom GeoJSON areas) by a value. --locations names the region-code
            column, --value/--agg the measure (row counts if omitted). Defaults
            to a token-free projection basemap; --map switches to MapLibre tiles.

qsv viz smart builds a one-page dashboard of subplots, reusing qsv's stats and frequency caches (the first run computes & caches stats; later runs are fast). It auto-picks panels, so no --x/--y is needed:

Per-column panels (flow in the grid below the overview rows, see --grid-cols):

  • continuous numeric -> box plot (quartiles from the stats cache; sample points overlaid by a size heuristic, see --box-points)
  • low-cardinality / boolean -> frequency bar chart
  • ID-like (near-unique) and all-empty columns are skipped

Overview panels (each leads the dashboard on its own full-width row):

  • KPI overview row (leads the dashboard when the dataset has headline numeric measures): a strip of "big number" tiles, one per headline measure (summed for extensive quantities, averaged for intensive ones). A measure tile becomes a GAUGE when the dictionary supplies a validated x-qsv.gauge_range that contains the value, and gains a "vs target" DELTA when it supplies an x-qsv.target (see --dictionary). Omitted for image exports and for datasets with no headline measure. (Overall dataset completeness - the share of non-empty cells - is a quiet "Completeness:" line in the header metadata table, not a KPI tile.)
  • pipeline funnel, when the dictionary DECLARES one (see --dictionary). Which columns are process stages, and in which direction, is semantics rather than a statistic - no column-name vocabulary settles it and no statistic does either - so a funnel is drawn ONLY from an explicit declaration, never guessed. Both encodings are supported: stages held in separate measure columns, and stages held as values of one category column. Costs one extra data pass over the declared stages only. Stage order is the declared order and is never re-sorted by size. For the column encoding, row-wise containment (does each stage nest inside the one before it?) is MEASURED and disclosed in the subtitle, but never refuses the panel: a pipeline whose stages overrun is a finding to name, not a reason to show nothing. Totals sum over the rows complete across every declared stage, so they do NOT match stats.sum; the subtitle always discloses that denominator. See also the standalone qsv viz funnel chart type, which takes its stage order from the file and needs no dictionary.
  • correlation heatmap, when 2+ continuous numeric columns exist (one extra data pass for Pearson correlations). If the strongest pair is at least moderately correlated, a drill-down is added beside it: a scatter (or a 2D density contour for large, overplotting datasets); with 3+ numeric columns, a 3D scatter of the strongest triple is added too.
  • time-series line, when an auto-detected date/datetime column and a continuous numeric column both exist.
  • geographic map, when a latitude/longitude pair is detected:
    • HTML uses a MapLibre tile map for a local extent, or an offline ScatterGeo projection world-overview for continental/global data.
    • static image export uses an offline ScatterGeo fit to the data extent (US-spanning data uses albers-usa); tile maps and 3D panels stay HTML-only, as tile maps need network tiles.
    • geographic outliers (points beyond the Tukey far-out fence of distances from the cluster centroid) get a distinct marker and are excluded from the spatial extent; the map zooms to the core, with a dotted no-fill box marking the full extent and (in HTML) Core/Full extent buttons. Outliers within the core's jurisdiction don't trigger the extent call-out.
    • with the geocode feature, the core extent (4 corners + center) is reverse-geocoded against the local Geonames index and drawn as a labeled bounding box with a location summary (e.g. "New York & New Jersey, United States"); outliers are called out with their count and jurisdiction. HTML points reveal city/state/country on hover (static exports omit it). The first run may download the index (~13MB, cached in ~/.qsv-cache); offline, the map renders without the overlay.
    • extents spanning the antimeridian (>180 degrees of longitude) are skipped.

Examples

Auto-dashboard for a dataset, opened in the browser

qsv viz smart data.csv --open

Auto-dashboard, at most 6 panels in a 3-column grid, top-5 categories per bar

qsv viz smart data.csv --max-charts 6 --grid-cols 3 --limit 5 -o dashboard.html

Bar chart of fruit prices, opened in the browser

qsv viz bar fruits.csv --x Fruit --y Price --title "Fruit prices" --open

Aggregate (sum) sales by region into a bar chart

qsv viz bar sales.csv --x region --y amount --agg sum -o sales.html

Scatter plot with a separate series (trace) per category

qsv viz scatter data.csv --x age --y income --series gender -o scatter.html

Bubble scatter: marker size by population, marker color by a numeric score

qsv viz scatter data.csv --x gdp --y life_exp --size population --color score -o bubble.html

Histogram of a numeric column with 30 bins

qsv viz histogram data.csv --x value --bins 30 -o hist.html

Box plot of a value column grouped by a category, exported to PNG (needs viz_static)

qsv viz box data.csv --y measurement --x group -o box.png

Box plot with every sample point overlaid (jittered) instead of just the outliers

qsv viz box data.csv --y measurement --box-points all -o box.html

Violin plot (KDE density curve + inner box) of a value column grouped by a category

qsv viz violin data.csv --y measurement --x group -o violin.html

Pie chart of category proportions (counts), as a donut

qsv viz pie data.csv --x category --donut -o pie.html

Funnel of a pipeline whose stages are ROWS (stage column + amount column)

qsv viz funnel pipeline.csv --x stage --y amount -o funnel.html

Correlation heatmap over all numeric columns

qsv viz heatmap data.csv -o corr.html

Heatmap pivot: average value per (region x product)

qsv viz heatmap sales.csv --x region --y product --z amount -o pivot.html

Candlestick chart from a date column and OHLC price columns

qsv viz candlestick prices.csv --x date --ohlc-open open --high high --low low --close close -o ohlc.html

Sankey flow diagram of source -> target weighted by value

qsv viz sankey flows.csv --source from --target to --value weight -o sankey.html

Radar chart comparing numeric metrics, one trace per team

qsv viz radar teams.csv --cols speed,power,range,accuracy --series team -o radar.html

Point map of earthquakes, marker color by magnitude and size by depth

qsv viz map quakes.csv --lat lat --lon lon --color magnitude --size depth -o map.html

Density heatmap of the same points, on a light Carto basemap

qsv viz map quakes.csv --lat lat --lon lon --density --style carto-positron -o heat.html

3D scatter of three numeric columns, colored by a fourth

qsv viz scatter3d data.csv --x length --y width --z height --color weight -o scatter3d.html

2D density contour of two numeric columns with a 40x40 grid

qsv viz contour data.csv --x height --y weight --bins 40 -o contour.html

Projection map of earthquakes (token-free), marker color by magnitude

qsv viz geo quakes.csv --lat lat --lon lon --color magnitude --projection natural-earth -o geo.html

Treemap of part-to-whole sales by region then category, sized by amount

qsv viz treemap sales.csv --cols region,category --value amount --agg sum -o treemap.html

Sunburst of a deep 3-level web-traffic hierarchy, sized by row count

qsv viz sunburst web.csv --cols source,campaign,landing_page -o sunburst.html

Choropleth coloring countries (ISO-3 codes) by a summed measure

qsv viz choropleth gdp.csv --locations iso3 --value gdp --agg sum -o choropleth.html

US-state choropleth of row counts per state (2-letter state codes)

qsv viz choropleth orders.csv --locations state --location-mode usa-states -o states.html

Custom GeoJSON regions on a MapLibre basemap, matched by a feature id

qsv viz choropleth counties.csv --locations fips --value pop --map --geojson counties.json --feature-id-key id -o counties.html

Reverse-geocode lat/lon points to ISO-3 codes, then count per country (needs geocode feature)

qsv viz choropleth stops.csv --geocode --lat lat --lon lon -o by_country.html

Point-in-polygon: bin lat/lon points into custom GeoJSON regions by count (no geocode)

qsv viz choropleth quakes.csv --lat lat --lon lon --geojson prefectures.geojson --feature-id-key properties.id -o by_pref.html

For more examples, see tests.

See also https://github.com/dathere/qsv/wiki/Visualization

Usage

qsv viz smart       [options] <input>
qsv viz bar         [options] <input>
qsv viz line        [options] <input>
qsv viz scatter     [options] <input>
qsv viz scatter3d   [options] <input>
qsv viz histogram   [options] <input>
qsv viz box         [options] <input>
qsv viz violin      [options] <input>
qsv viz pie         [options] <input>
qsv viz funnel      [options] <input>
qsv viz heatmap     [options] <input>
qsv viz contour     [options] <input>
qsv viz candlestick [options] <input>
qsv viz ohlc        [options] <input>
qsv viz sankey      [options] <input>
qsv viz radar       [options] <input>
qsv viz map         [options] <input>
qsv viz geo         [options] <input>
qsv viz choropleth  [options] <input>
qsv viz treemap     [options] <input>
qsv viz sunburst    [options] <input>
qsv viz icicle      [options] <input>
qsv viz splom       [options] <input>
qsv viz parcats     [options] <input>
qsv viz --help

Viz Options

        Option         Type Description Default
 ‑x,
‑‑x 
string Column for the x-axis / category / bin / group.
 ‑y,
‑‑y 
string Column for the y-axis / value.
 ‑z,
‑‑z 
string The z column: a heatmap pivot value (with --x and --y), or the third numeric axis for scatter3d.
 ‑‑cols  string Columns to use. For heatmap: numeric columns for the correlation matrix (default: all numeric). For radar: the numeric axes to plot. For treemap/sunburst/icicle: the categorical dimensions that form the hierarchy levels, outermost first (e.g. region,category,subcategory). For splom: the numeric columns to cross-plot (default: all numeric). For parcats: the categorical dimensions to flow across (best with 3-4).
 ‑‑series  string Column to split into multiple series (one trace per distinct value). Applies to bar, line, scatter, scatter3d, radar, map and geo.
 ‑‑color  string For scatter/scatter3d/map/geo: a numeric column to encode as marker color (a continuous colorscale with a colorbar). For categorical coloring, use the --series option instead. Cannot be combined with --series. In map density mode, this column is the heatmap weight.
 ‑‑size  string For scatter/scatter3d/map/geo: a numeric column to encode as marker size, producing a bubble chart (values are rescaled to a readable pixel range). Cannot be combined with --series. In map density mode, this column is the heatmap weight.
 ‑‑donut  flag Render a pie chart as a donut (with a center hole).
 ‑‑ohlc‑open  string Open-price column for candlestick/ohlc charts.
 ‑‑high  string High-price column for candlestick/ohlc charts.
 ‑‑low  string Low-price column for candlestick/ohlc charts.
 ‑‑close  string Close-price column for candlestick/ohlc charts.
 ‑‑source  string Source node column for a sankey diagram.
 ‑‑target  string Target node column for a sankey diagram.
 ‑‑value  string Flow value column for a sankey diagram. When omitted, each row counts as a flow of 1. For treemap/sunburst/icicle: a numeric measure summed per sector (when omitted, each row counts as 1).
 ‑‑sankey‑value‑order  flag Order sankey nodes by total flow (largest at the top of each column). By DEFAULT nodes use plotly's crossing-minimizing "snap" order, which packs the diagram more compactly; this opts into the flow-ranked initial ordering instead. Either way the rendered chart carries an on-screen "node order" button to flip between the two layouts, and link ribbons are always colored by their source node. Applies to the sankey chart and the smart dashboard flow panel.
 ‑‑bins  integer Number of bins. For histogram: bins along the x-axis (default: auto). For contour: the per-axis resolution of the density grid (default: 20).
 ‑‑agg  string For bar/line, aggregate the y values when the x value repeats. One of: sum, mean, count, min, max. For treemap/sunburst/icicle, only additive aggregations apply: count (default) or sum (requires --value).
 ‑‑box‑points  string Which sample points to draw alongside a box. Reading the raw values lets plotly render true Tukey whiskers (1.5*IQR) with the points beyond the fences as outliers. One of: outliers (only the outliers), all (every point, jittered), suspected (mark suspected outliers), none (no points, but still real Tukey whiskers). For viz box the default is outliers. For viz smart this flag OVERRIDES the default size-based heuristic, which overlays all points on a column with few non-null values (<=1,000) — unless the dashboard has more than 8 panels, where all-points cells turn to noise, so the overlay drops to outliers-only — and only the outliers for a medium one (<=10,000 values). Above that, a column that HAS outliers shows them as points on a precomputed quartile box (a single pass collects only the out-of-fence values, capped); a column with no outliers stays a fast cache-only quartile summary with no data re-scan. An explicit mode is applied to every box panel (one batched pass to read the values), except none, which keeps the cache-only box for BOX panels. A smart violin panel still renders under none, just with no sample points — its KDE needs the values anyway; combine with the violin option's off mode for the cache-only escape hatch. The same modes also pick the sample points drawn beside a violin, for viz violin and for the violin panels of viz smart — though a smart violin panel skips the size-based all upgrade (its KDE silhouette already shows the distribution) and overlays only the outliers unless an explicit mode is given.

Map Options

     Option      Type Description Default
 ‑‑lat  string Latitude column for a map (decimal degrees, -90 to 90).
 ‑‑lon  string Longitude column for a map (decimal degrees, -180 to 180).
 ‑‑text  string Column whose value labels each point on hover.
 ‑‑density  flag Render a density heatmap (DensityMap) instead of points. Weighted by the --color or --size column when given, else by a uniform weight. Cannot be combined with --series.
 ‑‑style  string MapLibre basemap style (all render without an access token): open-street-map (the default), carto-positron, carto-darkmatter, carto-voyager, white-bg, basic, streets, outdoors, light, dark, satellite, satellite-streets. The three carto styles also have label-free "-nolabels" variants (e.g. carto-positron-nolabels) that keep basemap place names from competing with a dense data overlay. open-street-map

Geo Options

     Option      Type Description Default
 ‑‑projection  string Map projection for viz geo. One of: natural-earth (the default), mercator, orthographic, equirectangular, albers-usa, robinson, winkel-tripel, mollweide, hammer, azimuthal-equal-area. viz geo also reuses the lat, lon, text, color, size and series options from map. natural-earth

Choropleth Options

       Option        Type Description Default
 ‑‑locations  string Column holding the region key for each row (an ISO-3 country code, a 2-letter US state code, a country name, or a GeoJSON feature id, per --location-mode). With --geocode, this instead names a place-name column to forward-geocode into region codes.
 ‑‑location‑mode  string How --locations values are matched to regions. One of: iso3 (the default, ISO-3166-1 alpha-3 country codes), usa-states (2-letter US state codes), country-names (full country names), geojson-id (match a --geojson feature id). iso3
 ‑‑color‑scale  string Colorscale for the region fill. One of: viridis (the default), cividis, greys, greens, blues, reds, ylgnbu, ylorrd, bluered, rdbu, portland, electric, jet, hot, blackbody, earth, picnic, rainbow. viridis
 ‑‑map  flag Render on a token-free MapLibre tile basemap (a ChoroplethMap) instead of the default projection basemap. Requires --geojson; feature-id-key defaults to id. Reuses --style for the basemap.
 ‑‑geojson  string Custom region polygons as a local file path or an http(s) URL to a GeoJSON FeatureCollection. May also be a shortcut name defined in the QSV_GEOJSON_SHORTCUTS env var (a JSON map of name to {path, id}); the shortcut's id sets --feature-id-key when you don't pass one. The source is validated up front. Required for --map, and for the geojson-id location mode. Also enables point-in-polygon binning: with --lat/--lon (and without --geocode), each row's point is binned into the region whose polygon contains it (exact, no geocoding) and colored by --value/--agg or counts. In viz smart, it also overlays the region boundaries on the map, labelling each with its --feature-name-key value (falling back to its id) — as on-map text on the projection/static map, or as a centroid hover marker on the interactive tile map (which culls on-map text). Labels are omitted above 60 regions.
 ‑‑feature‑id‑key  string Property path in each GeoJSON feature whose value matches an entry in the locations column, or that labels each binned region (e.g. id, properties.fips). id
 ‑‑feature‑name‑key  string GeoJSON property path whose value is shown as the human-readable region label in choropleth hover (e.g. properties.name). When omitted, common name keys are auto-detected; falls back to the feature id when absent.
 ‑‑geocode  flag Derive the region codes by reusing qsv's geocode engine (needs a build with the geocode feature). Either reverse-geocode the lat/lon points, or forward-geocode the locations name column. Only valid with location modes iso3 or usa-states. viz choropleth also reuses --value, --agg, --style and the lat/lon options.
 ‑‑no‑snap  flag For point-in-polygon binning (lat/lon points binned into a custom GeoJSON without geocoding): do not snap at all — drop every point that falls outside every region. By default an outside point instead snaps to its nearest region when within the snap-distance limit (see --snap-max-dist). Applies to both the viz choropleth command and the viz smart GeoJSON choropleth panel. A stderr note reports coverage either way; each snapping region's hover tallies the points it absorbed from outside, and snapped or dropped points are reported in a note beneath the map (or in the smart panel's title).
 ‑‑snap‑max‑dist  float For point-in-polygon binning: the farthest (in km) an outside point may snap to a region's boundary; points with no region within this distance are dropped. Distance is an equirectangular km approximation. When omitted, the cap is auto-derived from the GeoJSON's median region size (10% of the median bbox diagonal) and the lat/lon coordinate precision (coarse, few-decimal coordinates raise the cap to cover their quantization error), clamped to 0.1-100 km; a fixed 10 km is used only when neither signal is available. Applies to both the viz choropleth command and the viz smart GeoJSON choropleth panel; the coverage notes state the cap applied and how it was derived. Pass a large value for effectively unbounded snapping; cannot be combined with --no-snap.

Smart Options

        Option         Type Description Default
 ‑‑max‑charts  integer Maximum number of panels in the dashboard. 0 (the default) means auto: draw every eligible column (up to 64), for both HTML and static image export (png/svg/pdf/...). Up to 8 cartesian panels render as one typed subplot grid; beyond 8, HTML switches to an inline-div grid of independent plots, and static image export uses domain-positioned axes to fit them in one image. Set a positive to cap the panel count instead. Eligible columns beyond the cap are reported but not drawn. 0
 ‑‑grid‑cols  integer Number of columns in the dashboard grid for the per-column distribution panels. Overview panels (map/geo, correlation, time-series) always span the full width. 2
 ‑‑heatmap‑density  integer For the viz smart map panel: at or above mappable points, draw the core as a density heatmap (DensityMap) instead of markers. The heatmap keeps per-point hover (coordinates, plus the point's label). Defaults to 0 (disabled): dense point maps instead open as individual points with an in-map "Clusters/Points" toggle (collapse the dense areas into interactive count bubbles on demand) rather than aggregating into a static heat surface. Set a positive to opt back into the heatmap above that point count. 0
 ‑‑cluster  string For the viz smart map panel: whether to offer an in-map "Clusters/Points" toggle that collapses dense points into native MapLibre count bubbles (which expand back into individual, hoverable points on zoom-in). Hovering a bubble shows its point count; clicking it zooms to where that cluster breaks apart. The map always OPENS as individual points; the toggle switches clustering on. One of: auto, on, off. "auto" (the default) offers the toggle for a plain-marker core (no density heatmap, no bubble-size measure) once it reaches 1,000 points. "on" offers it whenever the core draws as markers, regardless of point count or a bubble-size measure. "off" omits the toggle, so points are always drawn plainly. Only affects smart. auto
 ‑‑photos  flag For the viz smart map panel: when a column holds image URLs (detected from the stats cache - an http(s) value ending in a common image extension), embed each point's image URL so that dwelling on a map point for 2 seconds opens that row's photo in a small preview card beside the pointer (arrow keys page through a row with several photos; Escape dismisses the card). Points that have photos say so in their hover label. When the image host allows cross-origin reads, fetched images are cached in the browser's IndexedDB, so re-dwelling a point or reloading the page serves them locally; otherwise the preview falls back to a normal image load served by the ordinary browser cache. OFF by default, and deliberately so: images load from whatever third-party host the DATA names, so enabling this makes everyone who opens the dashboard request those URLs directly (revealing their IP to that host). Nothing is fetched until a viewer dwells. Embedding every mapped point's URLs also grows the HTML. Applies to HTML output only - static image exports (PNG/SVG/PDF) are unaffected - and only on the tile-basemap map panel. Only affects smart.
 ‑‑limit  integer Top-N categories per frequency bar chart. 10
 ‑‑no‑nulls  flag Omit the "(NULL)" bar (empty cells) from frequency bar charts. By default viz smart shows a "(NULL)" bar, like qsv frequency.
 ‑‑no‑other  flag Omit the "Other (N)" aggregate bar from frequency bar charts. It collects the categories beyond --limit (N = how many distinct categories were rolled up) and is shown by default. When just ONE category is left over, it is charted under its own name instead of as an opaque "Other (1)" bar.
 ‑‑smarter  flag Before building the dashboard, run qsv moarstats --advanced to enrich the stats cache with distribution-shape statistics (bimodality, entropy, skewness, outlier share, Gini). This unlocks histograms for bimodal columns, frequency bars for concentrated high-cardinality columns, skew/outlier hints on box panels, and Lorenz curves for the most unequal additive measures (high Gini). Costs one extra pass over the data and writes .stats.csv, its sidecars, and an .idx index (like running qsv moarstats manually). On geocode-enabled builds it also enriches map point hovers with the US FIPS code and annotates the spatial-extent summary with the country's continent; the county is always shown in map hovers, with or without --smarter. Only affects smart. Applied only with default parsing; inputs using --no-headers or a custom --delimiter fall back to the standard dashboard.
 ‑‑hierarchy‑style  string For smart, the chart used for the categorical part-to-whole hierarchy panel (built when 2+ low-cardinality dimensions exist). One of: auto (default), treemap, sunburst, icicle. auto follows best practice — a treemap for a shallow 2-level hierarchy (accurate size comparison) and a sunburst for a deep 3-level one (parent child structure); icicle is an opt-in level-aligned alternative. Only affects smart.
 ‑‑dictionary  string Use a describegpt Data Dictionary to guide panel selection from each field's semantic role/concept (falling back to its content type) instead of relying on column statistics alone: dimensions and numeric codes (ward, census_tract, zone) become bars, measures get box/correlation/trend panels, date/datetime columns feed the time-series panel (not noisy frequency bars), identifiers / PII / free-text are skipped, and lat/lon feed the map. Field labels are shown as panel subtitles beneath the field-name titles. Columns the dictionary cannot classify still use the statistical heuristic. is one of: "infer" to run describegpt on the input now (with description, infer-content-type, two-pass and jsonschema output; requires an LLM configured) and use its output; or a path to an existing describegpt dictionary file (jsonschema or json). With "infer", the generated dictionary is saved beside the input as .schema.json so you can fine-tune it; if that file already exists, it is reused as-is (skipping the LLM) - edit it to fine-tune, or delete it to force a fresh re-infer. Generation/read failures soft-fall back to the stats-only dashboard. The dictionary also drives the KPI overview row via two optional per-field hints in a property's "x-qsv" object (edit them in the saved schema to fine-tune). A "gauge_range" of [min, max] on a continuous numeric measure renders its KPI tile as a GAUGE on that canonical scale (e.g. [0,1] for a ratio, [0,100] for a percent); qsv keeps it only when the observed data lies within the range, so a mis-scaled range can't draw a misleading dial, and "infer" emits it for canonical-scale measures. A "target" number on a measure renders a "vs target" DELTA against that goal (value minus target) - a GOAL you supply, never a fabricated prior-period baseline, so "infer" never emits it; hand-author it. The dictionary is also the ONLY source of the pipeline funnel panel, declared in the dataset-level "x-qsv" object as a "relationships" entry with "kind": "pipeline". Two encodings, both hand-editable: stages as COLUMNS - "members" lists the stage columns in process order, WIDEST/UPSTREAM FIRST (note this is the opposite direction from a "kind":"ordered" group, which ascends), e.g. {"kind":"pipeline", "members":["planned_amt","committed_amt","spent_amt"]} stages as ROW VALUES - "stage_column" names the category column, "stages" lists its values in process order, and an optional "value_column" names the measure to sum per stage (omit it to count rows), e.g. {"kind":"pipeline","members":["stage","revenue"], "stage_column":"stage", "stages":["Impression","Click","Lead","Conversion"], "value_column":"revenue"} Declared order is authoritative and is never re-sorted by size, so a stage that outruns its predecessor stays visible instead of being quietly reordered away. A declaration naming a missing column, or a stage that is an average/rate rather than a summable amount, is skipped with a note rather than erroring. Only affects smart.
 ‑‑dictionary‑context  string Path to a file with extra context about the dataset (a glossary, README, data dictionary, PDF, etc.) forwarded to describegpt as --context-file when --dictionary infer generates the dictionary. Better context yields better role/concept/label/grain tags, hence a better dashboard. Ignored unless --dictionary infer is used (it does not apply when reading an existing dictionary file). Only affects smart.
 ‑‑dict‑info  flag When a usable Data Dictionary is available (per --dictionary), add a "Data Dictionary" link beneath the dashboard title and an info icon on each panel title: hovering shows that column's dictionary description; clicking opens a human-friendly rendering of the dictionary in a side drawer NEXT TO the plots (embedded in the dashboard file - no extra file is written), scrolled to and highlighting that column's entry. The drawer is open by default on load and can be dismissed with its close button or Esc. The dictionary page carries a role-tinted table of contents and per-column "View chart" links back to the panels, plus a row of download buttons: the dictionary itself as JSON Schema, the frequency counts the dashboard actually charted, and every generated sidecar this run read (the stats cache and its metadata, the frequency cache when it was reused, and the bivariate stats CSV when freshly written). A sidecar qsv wrote but viz never read - the human-readable .stats.csv - is NOT offered, since nothing can show it describes the same computation the dashboard used. Every file is BUNDLED into the HTML, so anyone you send the dashboard to can download them with no access to your machine; absolute local paths are stripped from the embedded metadata so sharing a dashboard doesn't disclose your directory layout. Sidecars over 4 MB are skipped with a note. The drawer's popout button opens the same document in its own browser tab instead (needs a browser that allows user-initiated pop-ups). HTML output only; ignored with a note when no dictionary is available or when exporting an image. Only affects smart.
 ‑‑dataset‑pid  string A persistent identifier (PID) for the dataset - typically a full URL such as a DOI (https://doi.org/10.1234/abc) or other citable link. When set, a "PID" row is added to the metadata table at the top of the dashboard. http(s) and mailto values become a clickable link (opened in a new tab); any other scheme is shown as plain text rather than linked. HTML output only. Only affects smart.
 ‑‑bivariate  flag Add two pairwise-association overview panels driven by qsv moarstats --bivariate: a normalized mutual information (NMI) heatmap over every column pair (works for numeric AND categorical columns, unlike the Pearson-only correlation heatmap), plus a ranked "top relationships" bar of the strongest pairs when there are more than 8 chartable columns. The ranked bar (not the heatmap, which still shows every pair) requires a pair's co-occurring row count to be at least 10% of the best-supported pair's, so a technically-perfect NMI from two sparsely-populated columns that only ever co-occur in a narrow row slice can't crowd out a more broadly meaningful association; each bar's hover shows its co-occurring row count. A numeric pair whose Spearman rank correlation diverges sharply from its Pearson correlation is flagged "nonlinear" in the hover. Identifier / PII / free-text columns (per --dictionary) and map lat/lon columns are excluded. This automatically turns on --smarter, and when --dictionary isn't already set, also turns on --dictionary infer (so the PII/identifier exclusion has semantic signal to work with). Capped at 50 columns (1,225 pairs); wider datasets skip these panels with a warning (run qsv moarstats --bivariate directly for the full pairwise output). Only affects smart.
 ‑‑log‑scale  string Use a logarithmic y-axis for panels with a high dynamic range: frequency bar panels whose tallest bar dwarfs the rest (e.g. a large "(NULL)" or "Other (N)" bucket), so the small categories stay visible; and box panels of an all-positive column whose observed max/min ratio is huge (a box otherwise squashed against its extremes). One of: auto, on, off. "auto" (the default) switches a panel to a log y-axis only when its dynamic range is high; "on" forces a log y-axis on every frequency panel and every all-positive box panel; "off" keeps the linear axes. Only affects smart. auto
 ‑‑violin  string Draw distribution panels as violins (a box plot wrapped in a KDE density silhouette — a strict superset of a plain box) instead of boxes. One of: auto, on, off. "auto" (the default) draws a violin for every continuous column EXCEPT those on a log value axis (the KDE is estimated in linear space, which a log axis would geometrically distort) and those with fewer than 20 distinct values or fewer than 50 non-null observations (too few for a meaningful KDE — the curve would be smoothing artifact) — all keep an honest box; "on" also violins those; "off" never draws violins. Violin KDEs are clamped to each column's observed range (Plotly spanmode "hard") so a bounded or discrete measure can't show density past a natural limit. A column with at most 10,000 non-null values gets an exact violin (with outlier points, like a raw box); up to 30,000 values (one-fifth of the smart point budget, so it scales with QSV_VIZ_MAX_POINTS) still draws an exact violin but drops the point overlay; a larger column draws its silhouette and inner box from a deterministic sample of at most that many evenly strided values, carries no point overlay (a sample misses the true extremes), and is titled "(sampled)". An explicit all, outliers or suspected mode given via the box-points option instead collects every value for every panel, violins included; that option's none mode just hides a violin's points. Only affects smart. auto
 ‑‑title  string Chart title.
 ‑‑x‑title  string X-axis title. (defaults to the x column name)
 ‑‑y‑title  string Y-axis title. (defaults to the y column name)
 ‑‑y‑range  string Fix the y-axis to an explicit min:max range (two colon- separated numbers, e.g. -10:55) instead of autoscaling; points outside are clipped from view. Handy when one extreme outlier squashes the rest. Applies to cartesian charts (bar/line/scatter/histogram/box/violin/heatmap/ contour). Pass a negative min with =: --y-range=-10:55.
 ‑‑rangeslider  flag Add a draggable range-slider (a navigator strip) under the x-axis for panning and zooming. Best for an ordered x-axis (time series, line, candlestick/ohlc). Applies to cartesian charts (bar/line/scatter/histogram/box/violin/candlestick/ ohlc); off by default.
 ‑‑slider  string Animate the chart over a column: each distinct value of the given column becomes an animation frame, with a Play/Pause button and a slider to scrub through the frames (Gapminder- style). Supported for bar/line/scatter and geo, and may be split into animated traces with the --series option. (Not supported for viz map — the MapLibre basemap can't animate; use viz geo for an animated point map.) For smart, this controls whether one animated relationship-over-time panel is added: the numeric pair whose per-time-bucket centroid path bends the most (a trailing-window scatter colored by time bucket), or an animated geo map of global-extent dated points, or a Gapminder entity-bubble chart (at most one is shown; when several qualify the bubble wins, then the geo map, then the pair). auto (default) adds one only on a strong signal (a date column and enough time buckets); on lowers the bar (as few as two buckets) but still requires a genuinely drifting or animatable relationship; off never does. Axis ranges are pinned across frames so nothing jumps.
 ‑‑slider‑speed  integer Milliseconds each animation frame is shown while playing. 800
 ‑‑slider‑cumulative  flag Accumulate rows across frames: frame N includes every row whose --slider value is at or below the Nth value, so the animation builds up cumulatively instead of replacing each step. Applies to bar/line/scatter and geo.
 ‑‑annotation  string Caption note drawn at the bottom of the plot (e.g. to note a clipped outlier). Cartesian charts only.
 ‑‑theme  string Plotly theme that drives the chart's overall look (background, fonts, axis styling). One of: default, plotly_white, plotly_dark, seaborn, seaborn_whitegrid, seaborn_dark, matplotlib, plotnine (case-insensitive; hyphens accepted). When omitted, qsv's built-in look is used. Applies to all chart types, including smart.
 ‑‑width  integer Image width in pixels for static export. Default 1000; for smart, auto-scaled to the grid's column count.
 ‑‑height  integer Image height in pixels for static export. Default 600; for smart, auto-scaled to the number of panel rows.
 ‑‑scale  float Image scale factor (static export). 1.0
 ‑‑open  flag Open the generated chart in the default browser/viewer.

Common Options

     Option      Type Description Default
 ‑h,
‑‑help 
flag Display this message
 ‑o,
‑‑output 
string Write output to instead of stdout. The chart format is inferred from the extension: .html (default), .png, .svg, .pdf, .jpeg, .webp.
 ‑d,
‑‑delimiter 
string The field delimiter for reading CSV data. Must be a single character. (default: ,)
 ‑n,
‑‑no‑headers 
flag When set, the first row will not be interpreted as headers. Columns can then only be selected by index.

Source: src/cmd/viz.rs | Table of Contents | README