Altair Python
Build the smallest valid declarative specification that answers the stated
question. A chart maps data fields to visual channels; it is not a sequence of
drawing commands and does not contain rendered pixels.
Boundary
Use this skill when a project imports Altair or explicitly requests Altair or a
Vega-Lite specification. Do not introduce it into Plotly/Matplotlib-only code,
Streamlit application-state work, or a pure dataframe transformation. Preserve
the required artifact boundary: Python chart object, JSON spec, HTML, or image.
Know the objects
| Object |
Runtime meaning |
Use |
Chart |
Declarative unit specification over a data source |
Add one mark, encodings, transforms, parameters, and properties. |
| Mark |
Geometric representation such as point, line, bar, area, rect, rule, or text |
Choose from the analytical task and data grain. |
| Encoding channel |
Mapping from field/value/datum/expression to x, y, color, size, shape, tooltip, facet, etc. |
Declare field type, aggregation, scale, axis, legend, sort. |
| Transform |
Vega-Lite data operation inside the specification |
Filter, calculate, aggregate, bin, time unit, window, lookup, fold, and related view-local work. |
| Parameter/selection |
Named interactive value or selected data subset |
Drive filters, conditions, domains, or bound controls. |
| Compound chart |
Layer, facet, repeat, horizontal/vertical concat |
Compose related views with explicit shared/independent guides. |
| Serialized spec |
Validated Vega-Lite JSON-compatible tree |
Test, inspect, embed, save, or hand to a renderer. |
Read the declarative grammar before choosing mark,
grain, encoding type, aggregation, or interaction.
Ordered workflow
- State the analytical question, one-row data grain, fields, missing-value
policy, required ordering, and output host before selecting a mark.
- Decide whether the displayed grain equals input rows or a derived aggregate,
bin, window, fold, lookup, or time unit. Make that transformation explicit.
- Choose the mark from the relationship: position for quantitative comparison,
line only for meaningful ordered continuity, bar for discrete magnitude,
rect for two-dimensional bins, rule/text only as annotation.
- Encode fields with explicit semantic types when inference could be wrong:
quantitative, temporal, ordinal, nominal, or geographic. Configure sort,
scale, axis, legend, and tooltip from the contract.
- Add composition or interaction only when it serves the question. Name
parameters and resolve scales/guides deliberately.
- Decide where data lives: inline values, URL, named dataset, or a configured
transformer. Never disable a row safeguard merely to silence an error.
- Validate/inspect the serialized spec and test semantic nodes. Render in the
real host only when visual integration is part of completion.
Intent to specification
| Question |
Typical grammar |
Invariant |
| Relationship between two measures |
point with quantitative x/y |
One mark per intended observation; reveal overplotting when material. |
| Trend across ordered time |
line with temporal x and quantitative y |
Time is sorted; missing intervals/series do not imply false continuity. |
| Compare categories |
bar/tick with nominal/ordinal category and quantitative value |
Aggregation and category order are explicit; zero baseline policy is defensible. |
| Distribution |
binned bar, tick, boxplot, density, or ECDF-style transform |
Bin/statistic and units are visible. |
| Two-dimensional magnitude |
rect/heatmap with x/y bins and color |
Color type/domain and missing bins are defined. |
| Same measure across groups |
facet/repeat small multiples |
Comparable scales are shared unless independent scales are an explicit need. |
| Overlay observations and summary |
layer charts over common data/encodings |
Layer order and scale resolution preserve meaning. |
| Interactive subset |
parameter/selection plus conditional encoding or filter |
Empty-selection and initial-state behavior are defined. |
Canonical anchor
import altair as alt
def sales_chart(data):
return (
alt.Chart(data)
.mark_line(point=True)
.encode(
x=alt.X("date:T", title="Date"),
y=alt.Y("revenue:Q", title="Revenue"),
color=alt.Color("region:N", title="Region"),
tooltip=[
alt.Tooltip("date:T"),
alt.Tooltip("region:N"),
alt.Tooltip("revenue:Q", format=",.2f"),
],
)
.properties(title="Revenue by region")
)
The return value remains a chart/specification. Do not call display/save inside
a reusable chart builder unless that side effect is its public contract.
Data and transform boundary
- Transform in Python when the result is shared outside the chart, requires
domain validation, or is easier to unit-test as data.
- Transform in Vega-Lite when it is view-local, must react to a parameter, or
should remain coupled to the visualization grammar.
- Do not both pre-aggregate and declare the same aggregation in an encoding.
- Explicitly retain group keys through aggregate/window operations.
- Treat Altair data transformers as serialization/loading policy, not
Vega-Lite transforms. Sampling changes the analytical result and requires an
explicit statistical decision.
- For large data, aggregate/filter upstream or use an intentional external-data
path. Never globally disable maximum-row protection as a default fix.
Read data and transform rules.
Composition and interaction
Layer when views share coordinates; facet/repeat when subsets need comparable
panels; concatenate when views have distinct coordinates. For compound views,
state whether x/y scales, legends, and axes are shared or independent. Define a
parameter once at the correct scope, then use it through a filter, condition,
or domain. Do not add .interactive() as a substitute for a specified
selection behavior.
Read composition, export, and testing.
Verification
Inspect the installed version of Altair and the target renderer before using a
drift-sensitive parameter/transform/export signature. This foundry had no
Altair installation during authoring, so examples are primary-source-grounded
but not locally rendered.
Completion requires: correct input and displayed grain; explicit field types,
aggregation, sort, and scale semantics; stable null/empty behavior; no duplicate
aggregation; intentional data transport; valid serialized specification;
semantic tests for marks/encodings/transforms/parameters; and a host render or
clearly reported missing render evidence when appearance matters.
References
- Declarative grammar and encoding
- Data and transform boundary
- Composition, export, and testing
1---2name: altair-python3description: Build, review, debug, or test declarative statistical visualizations in Python with Altair and Vega-Lite, including chart marks, typed encodings, transforms, parameters, layers, facets, and specification export.4---56# Altair Python78Build the smallest valid declarative specification that answers the stated9question. A chart maps data fields to visual channels; it is not a sequence of10drawing commands and does not contain rendered pixels.1112## Boundary1314Use this skill when a project imports Altair or explicitly requests Altair or a15Vega-Lite specification. Do not introduce it into Plotly/Matplotlib-only code,16Streamlit application-state work, or a pure dataframe transformation. Preserve17the required artifact boundary: Python chart object, JSON spec, HTML, or image.1819## Know the objects2021| Object | Runtime meaning | Use |22|---|---|---|23| `Chart` | Declarative unit specification over a data source | Add one mark, encodings, transforms, parameters, and properties. |24| Mark | Geometric representation such as point, line, bar, area, rect, rule, or text | Choose from the analytical task and data grain. |25| Encoding channel | Mapping from field/value/datum/expression to x, y, color, size, shape, tooltip, facet, etc. | Declare field type, aggregation, scale, axis, legend, sort. |26| Transform | Vega-Lite data operation inside the specification | Filter, calculate, aggregate, bin, time unit, window, lookup, fold, and related view-local work. |27| Parameter/selection | Named interactive value or selected data subset | Drive filters, conditions, domains, or bound controls. |28| Compound chart | Layer, facet, repeat, horizontal/vertical concat | Compose related views with explicit shared/independent guides. |29| Serialized spec | Validated Vega-Lite JSON-compatible tree | Test, inspect, embed, save, or hand to a renderer. |3031Read [the declarative grammar](references/grammar.md) before choosing mark,32grain, encoding type, aggregation, or interaction.3334## Ordered workflow35361. State the analytical question, one-row data grain, fields, missing-value37 policy, required ordering, and output host before selecting a mark.382. Decide whether the displayed grain equals input rows or a derived aggregate,39 bin, window, fold, lookup, or time unit. Make that transformation explicit.403. Choose the mark from the relationship: position for quantitative comparison,41 line only for meaningful ordered continuity, bar for discrete magnitude,42 rect for two-dimensional bins, rule/text only as annotation.434. Encode fields with explicit semantic types when inference could be wrong:44 quantitative, temporal, ordinal, nominal, or geographic. Configure sort,45 scale, axis, legend, and tooltip from the contract.465. Add composition or interaction only when it serves the question. Name47 parameters and resolve scales/guides deliberately.486. Decide where data lives: inline values, URL, named dataset, or a configured49 transformer. Never disable a row safeguard merely to silence an error.507. Validate/inspect the serialized spec and test semantic nodes. Render in the51 real host only when visual integration is part of completion.5253## Intent to specification5455| Question | Typical grammar | Invariant |56|---|---|---|57| Relationship between two measures | point with quantitative x/y | One mark per intended observation; reveal overplotting when material. |58| Trend across ordered time | line with temporal x and quantitative y | Time is sorted; missing intervals/series do not imply false continuity. |59| Compare categories | bar/tick with nominal/ordinal category and quantitative value | Aggregation and category order are explicit; zero baseline policy is defensible. |60| Distribution | binned bar, tick, boxplot, density, or ECDF-style transform | Bin/statistic and units are visible. |61| Two-dimensional magnitude | rect/heatmap with x/y bins and color | Color type/domain and missing bins are defined. |62| Same measure across groups | facet/repeat small multiples | Comparable scales are shared unless independent scales are an explicit need. |63| Overlay observations and summary | layer charts over common data/encodings | Layer order and scale resolution preserve meaning. |64| Interactive subset | parameter/selection plus conditional encoding or filter | Empty-selection and initial-state behavior are defined. |6566## Canonical anchor6768```python69import altair as alt707172def sales_chart(data):73 return (74 alt.Chart(data)75 .mark_line(point=True)76 .encode(77 x=alt.X("date:T", title="Date"),78 y=alt.Y("revenue:Q", title="Revenue"),79 color=alt.Color("region:N", title="Region"),80 tooltip=[81 alt.Tooltip("date:T"),82 alt.Tooltip("region:N"),83 alt.Tooltip("revenue:Q", format=",.2f"),84 ],85 )86 .properties(title="Revenue by region")87 )88```8990The return value remains a chart/specification. Do not call display/save inside91a reusable chart builder unless that side effect is its public contract.9293## Data and transform boundary9495- Transform in Python when the result is shared outside the chart, requires96 domain validation, or is easier to unit-test as data.97- Transform in Vega-Lite when it is view-local, must react to a parameter, or98 should remain coupled to the visualization grammar.99- Do not both pre-aggregate and declare the same aggregation in an encoding.100- Explicitly retain group keys through aggregate/window operations.101- Treat Altair data transformers as serialization/loading policy, not102 Vega-Lite transforms. Sampling changes the analytical result and requires an103 explicit statistical decision.104- For large data, aggregate/filter upstream or use an intentional external-data105 path. Never globally disable maximum-row protection as a default fix.106107Read [data and transform rules](references/data-transforms.md).108109## Composition and interaction110111Layer when views share coordinates; facet/repeat when subsets need comparable112panels; concatenate when views have distinct coordinates. For compound views,113state whether x/y scales, legends, and axes are shared or independent. Define a114parameter once at the correct scope, then use it through a filter, condition,115or domain. Do not add `.interactive()` as a substitute for a specified116selection behavior.117118Read [composition, export, and testing](references/composition-testing.md).119120## Verification121122Inspect the installed version of Altair and the target renderer before using a123drift-sensitive parameter/transform/export signature. This foundry had no124Altair installation during authoring, so examples are primary-source-grounded125but not locally rendered.126127Completion requires: correct input and displayed grain; explicit field types,128aggregation, sort, and scale semantics; stable null/empty behavior; no duplicate129aggregation; intentional data transport; valid serialized specification;130semantic tests for marks/encodings/transforms/parameters; and a host render or131clearly reported missing render evidence when appearance matters.132133## References134135- [Declarative grammar and encoding](references/grammar.md)136- [Data and transform boundary](references/data-transforms.md)137- [Composition, export, and testing](references/composition-testing.md)