viz
June 29, 2026 · View on GitHub
Generate interactive charts (bar, line, scatter, histogram, box, pie, heatmap, candlestick/ohlc, sankey, radar, treemap, sunburst, geographic maps) and an auto-dashboard (
viz smart) from CSV data using plotly.viz smart"neuro-symbolically" picks an appropriate chart per column using the dataset's statistics, frequency distributions & data dictionary with integrated Geonames geocoding & optional LLM metadata inferencing. Outputs self-contained, interactive HTML or static PNG/SVG/PDF/JPEG/WebP with theviz_staticfeature. (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 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). 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.
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.
pie Proportions. --x = label column, optional --y = value column.
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.
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):
- 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 Mapbox 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
geocodefeature, 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
Pie chart of category proportions (counts), as a donut
qsv viz pie data.csv --x category --donut -o pie.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 pie [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 --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: the categorical dimensions that form the hierarchy levels, outermost first (e.g. region,category,subcategory). | |
‑‑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: a numeric measure summed per sector (when omitted, each row counts as 1). | |
‑‑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, 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 for small data (<=1,000 rows) and only the outliers for medium data (<=10,000 rows). 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 always keeps the cache-only box. |
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 (DensityMapbox) instead of points. Weighted by the --color or --size column when given, else by a uniform weight. Cannot be combined with --series. | |
‑‑style | string | Map basemap style. Token-free styles: open-street-map (the default), carto-positron, carto-darkmatter, stamen-terrain, stamen-toner, stamen-watercolor, white-bg. Mapbox-hosted styles (basic, streets, outdoors, light, dark, satellite, satellite-streets) require --mapbox-token. | open-street-map |
‑‑mapbox‑token | string | Mapbox access token, required only for the mapbox-hosted basemap styles listed above. Can also be set with the QSV_MAPBOX_TOKEN environment variable (the --mapbox-token flag takes precedence). |
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 and --feature-id-key. Reuses --style for the basemap. | |
‑‑geojson | string | Custom region polygons as a local file path or an http(s) URL to a GeoJSON FeatureCollection. 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. | |
‑‑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 dropped points are reported 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. Defaults to 10 km, for both the viz choropleth command and the viz smart GeoJSON choropleth panel. 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 | 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 |
‑‑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. | |
‑‑smarter | flag | Before building the dashboard, run qsv moarstats --advanced to enrich the stats cache with distribution-shape statistics (bimodality, entropy, skewness, outlier share). This unlocks histograms for bimodal columns, frequency bars for concentrated high-cardinality columns, and skew/outlier hints on box panels. Costs one extra pass over the data and writes qsv moarstats manually). 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. 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). Only affects smart. | |
‑‑dictionary | string | EXPERIMENTAL. 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 become panel titles. Columns the dictionary cannot classify still use the statistical heuristic. 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. | |
‑‑log‑scale | string | Use a logarithmic y-axis for frequency bar panels whose tallest bar dwarfs the rest (e.g. a large "(NULL)" or "Other (N)" bucket), so the small categories stay visible. 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; "off" keeps the linear axes. 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) | |
‑‑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 | |
‑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