├── altair ├── sphinxext │ └── __init__.py ├── tests │ └── __init__.py ├── examples │ ├── tests │ │ ├── __init__.py │ │ └── test_examples.py │ ├── strip_plot.py │ ├── bubble_plot.py │ ├── grouped_bar_chart.py │ ├── trellis_scatter_plot.py │ ├── trail_marker.py │ ├── layered_area_chart.py │ ├── trellis_area.py │ ├── bar_chart_horizontal.py │ ├── multiple_marks.py │ ├── simple_stacked_area_chart.py │ ├── grouped_bar_chart_horizontal.py │ ├── binned_scatterplot.py │ ├── slope_graph.py │ ├── layered_bar_chart.py │ ├── simple_bar_chart.py │ ├── simple_histogram.py │ ├── interactive_scatter_plot.py │ ├── stacked_bar_chart.py │ ├── normalized_stacked_area_chart.py │ ├── table_bubble_plot_github.py │ ├── trellis_histogram.py │ ├── line_chart_with_points.py │ ├── simple_line_chart.py │ ├── multi_series_line.py │ ├── gantt_chart.py │ ├── horizontal_stacked_bar_chart.py │ ├── line_percent.py │ ├── binned_heatmap.py │ ├── normalized_stacked_bar_chart.py │ ├── bar_chart_with_mean_line.py │ ├── bar_and_line_with_dual_axis.py │ ├── filled_step_chart.py │ ├── trellis_stacked_bar_chart.py │ ├── multifeature_scatter_plot.py │ ├── choropleth.py │ ├── stacked_bar_chart_sorted_segments.py │ ├── streamgraph.py │ ├── histogram_with_a_global_mean_overlay.py │ ├── __init__.py │ ├── bar_chart_with_negatives.py │ ├── bar_chart_with_labels.py │ ├── interactive_brush.py │ ├── bar_chart_sorted.py │ ├── scatter_tooltips.py │ ├── trellis_area_sort_array.py │ ├── simple_heatmap.py │ ├── scatter_with_labels.py │ ├── one_dot_per_zipcode.py │ ├── scatter_href.py │ ├── step_chart.py │ ├── scatter_matrix.py │ ├── anscombe_plot.py │ ├── gapminder_bubble_plot.py │ ├── percentage_of_total.py │ ├── interval_selection.py │ ├── layer_line_color_rule.py │ ├── scatter_linked_brush.py │ ├── bar_chart_with_highlighted_bar.py │ ├── cumulative_wiki_donations.py │ ├── line_with_ci.py │ ├── iowa_electricity.py │ ├── connected_scatterplot.py │ ├── natural_disasters.py │ ├── choropleth_repeat.py │ ├── weather_heatmap.py │ ├── layered_chart_bar_mark.py │ ├── bar_chart_with_highlighted_segment.py │ ├── airports.py │ ├── world_projections.py │ ├── selection_histogram.py │ ├── error_bars_with_ci.py │ ├── layered_heatmap_text.py │ ├── parallel_coordinates.py │ ├── selection_layer_bar_month.py │ ├── top_k_items.py │ ├── layered_histogram.py │ ├── multiline_highlight.py │ ├── isotype_grid.py │ ├── us_population_over_time.py │ ├── stem_and_leaf.py │ ├── axes_scales.py │ ├── boxplot_max_min.py │ ├── ranged_dot_plot.py │ ├── simple_scatter_with_errorbars.py │ ├── us_state_capitals.py │ ├── horizon_graph.py │ ├── interactive_layered_crossfilter.py │ ├── beckers_barley_trellis_plot.py │ ├── dot_dash_plot.py │ ├── poly_fit.py │ ├── interactive_cross_highlight.py │ ├── scatter_marginal_hist.py │ ├── us_employment.py │ ├── top_k_letters.py │ ├── us_population_pyramid_over_time.py │ ├── scatter_with_histogram.py │ ├── seattle_weather_interactive.py │ ├── co2_concentration.py │ ├── london_tube.py │ ├── select_detail.py │ ├── multiline_tooltip.py │ ├── falkensee.py │ ├── isotype_emoji.py │ └── multiple_interactions.py ├── expr │ ├── tests │ │ ├── __init__.py │ │ └── test_expr.py │ ├── __init__.py │ └── consts.py ├── utils │ ├── tests │ │ ├── __init__.py │ │ ├── test_server.py │ │ ├── test_execeval.py │ │ ├── test_html.py │ │ ├── test_plugin_registry.py │ │ ├── test_utils.py │ │ └── test_data.py │ ├── theme.py │ ├── _py3k_compat.py │ ├── urls.py │ ├── __init__.py │ ├── execeval.py │ └── mimebundle.py ├── vegalite │ ├── tests │ │ ├── __init__.py │ │ └── test_common.py │ ├── v2 │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── test_display.py │ │ │ └── test_renderers.py │ │ ├── schema │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── html.py │ │ ├── theme.py │ │ └── data.py │ ├── __init__.py │ ├── api.py │ ├── schema.py │ ├── v1 │ │ ├── schema │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── html.py │ │ ├── theme.py │ │ └── data.py │ ├── display.py │ └── data.py ├── vega │ ├── __init__.py │ ├── v2 │ │ ├── schema │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── data.py │ │ └── display.py │ ├── v3 │ │ ├── schema │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── data.py │ │ └── display.py │ ├── v4 │ │ ├── schema │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── data.py │ │ └── display.py │ ├── display.py │ └── data.py ├── __init__.py └── datasets.py ├── tools └── schemapi │ ├── tests │ ├── __init__.py │ ├── test_utils.py │ └── test_decorator.py │ ├── __init__.py │ └── decorator.py ├── images └── cars.png ├── doc ├── requirements.txt ├── _static │ ├── favicon.ico │ ├── gray-square.png │ ├── altair-logo-light.png │ ├── altair-plot.css │ ├── custom.css │ ├── theme_overrides.css │ ├── chart.html │ └── altair-gallery.css ├── .gitignore ├── _templates │ └── class.rst ├── sync_website.sh ├── getting_started │ └── overview.rst ├── user_guide │ ├── importing.rst │ ├── renderers.rst │ ├── custom_renderers.rst │ ├── ecosystem.rst │ └── marks.rst └── index.rst ├── design ├── altair-logo.png ├── altair-logo-light.png ├── altair-logo.svg └── altair-logo-light.svg ├── paper ├── seattle_weather_interactive.png └── paper.bib ├── requirements.txt ├── MANIFEST.in ├── requirements_dev.txt ├── setup.cfg ├── Makefile ├── .travis.yml ├── CONTRIBUTING.md ├── .gitignore ├── LICENSE ├── RELEASING.md ├── NOTES_FOR_MAINTAINERS.md └── setup.py /altair/sphinxext/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/examples/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/expr/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/utils/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/vegalite/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/schemapi/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/vegalite/v2/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /altair/vega/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .v4 import * 3 | -------------------------------------------------------------------------------- /altair/vegalite/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .v2 import * 3 | -------------------------------------------------------------------------------- /altair/vegalite/api.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .v2.api import * 3 | -------------------------------------------------------------------------------- /images/cars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/images/cars.png -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | jinja2 3 | numpydoc 4 | pillow 5 | sphinx_rtd_theme 6 | -------------------------------------------------------------------------------- /design/altair-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/design/altair-logo.png -------------------------------------------------------------------------------- /doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/doc/_static/favicon.ico -------------------------------------------------------------------------------- /altair/vegalite/schema.py: -------------------------------------------------------------------------------- 1 | """Altair schema wrappers""" 2 | # flake8: noqa 3 | from .v2.schema import * 4 | -------------------------------------------------------------------------------- /design/altair-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/design/altair-logo-light.png -------------------------------------------------------------------------------- /doc/_static/gray-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/doc/_static/gray-square.png -------------------------------------------------------------------------------- /doc/_static/altair-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/doc/_static/altair-logo-light.png -------------------------------------------------------------------------------- /paper/seattle_weather_interactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0101011/altair/master/paper/seattle_weather_interactive.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | entrypoints 2 | jinja2 3 | jsonschema 4 | numpy 5 | pandas 6 | six 7 | toolz 8 | typing>=3.6;python_version<"3.5" 9 | -------------------------------------------------------------------------------- /altair/vega/v2/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .core import * 3 | 4 | SCHEMA_VERSION = 'v2.6.5' 5 | SCHEMA_URL = 'https://vega.github.io/schema/vega/v2.6.5.json' 6 | -------------------------------------------------------------------------------- /altair/vega/v3/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .core import * 3 | 4 | SCHEMA_VERSION = 'v3.3.1' 5 | SCHEMA_URL = 'https://vega.github.io/schema/vega/v3.3.1.json' 6 | -------------------------------------------------------------------------------- /altair/vega/v4/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .core import * 3 | 4 | SCHEMA_VERSION = 'v4.0.0' 5 | SCHEMA_URL = 'https://vega.github.io/schema/vega/v4.0.0.json' 6 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | 3 | # gallery is auto-generated; don't version-control it 4 | gallery 5 | _images 6 | 7 | # generated class documentation 8 | user_guide/generated 9 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.md 2 | include Makefile 3 | include LICENSE 4 | include CHANGES.md 5 | include requirements.txt 6 | include requirements_dev.txt 7 | recursive-include altair *.py *.json *.ipynb *.html 8 | -------------------------------------------------------------------------------- /altair/vegalite/v1/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .core import * 3 | from .channels import * 4 | SCHEMA_VERSION = 'v1.3.1' 5 | SCHEMA_URL = 'https://vega.github.io/schema/vega-lite/v1.3.1.json' 6 | -------------------------------------------------------------------------------- /altair/vegalite/v2/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .core import * 3 | from .channels import * 4 | SCHEMA_VERSION = 'v2.6.0' 5 | SCHEMA_URL = 'https://vega.github.io/schema/vega-lite/v2.6.0.json' 6 | -------------------------------------------------------------------------------- /altair/expr/__init__.py: -------------------------------------------------------------------------------- 1 | """Tools for creating transform & filter expressions with a python syntax""" 2 | # flake8: noqa 3 | from .core import datum, Expression 4 | from .funcs import * 5 | from .consts import * 6 | -------------------------------------------------------------------------------- /doc/_static/altair-plot.css: -------------------------------------------------------------------------------- 1 | .vega-actions a { 2 | margin-right: 12px; 3 | color: #757575; 4 | font-weight: normal; 5 | font-size: 13px; 6 | } 7 | 8 | .vega-embed { 9 | margin-bottom: 20px; 10 | margin-top: 20px; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /altair/vega/v2/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .display import vega, Vega, renderers 3 | from .schema import * 4 | 5 | from .data import ( 6 | pipe, curry, limit_rows, 7 | sample, to_json, to_csv, to_values, 8 | default_data_transformer 9 | ) 10 | -------------------------------------------------------------------------------- /altair/vega/v3/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .display import vega, Vega, renderers 3 | from .schema import * 4 | 5 | from .data import ( 6 | pipe, curry, limit_rows, 7 | sample, to_json, to_csv, to_values, 8 | default_data_transformer 9 | ) 10 | -------------------------------------------------------------------------------- /altair/vega/v4/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .display import vega, Vega, renderers 3 | from .schema import * 4 | 5 | from .data import ( 6 | pipe, curry, limit_rows, 7 | sample, to_json, to_csv, to_values, 8 | default_data_transformer 9 | ) 10 | -------------------------------------------------------------------------------- /altair/utils/theme.py: -------------------------------------------------------------------------------- 1 | """Utilities for registering and working with themes""" 2 | 3 | from .plugin_registry import PluginRegistry 4 | from typing import Callable 5 | 6 | ThemeType = Callable[..., dict] 7 | 8 | class ThemeRegistry(PluginRegistry[ThemeType]): 9 | pass 10 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | flake8 2 | pytest 3 | sphinx 4 | m2r 5 | docutils 6 | vega_datasets 7 | recommonmark 8 | 9 | 10 | ipython<6; python_version < '3' # ipython 6 not compatible with python 2 11 | ipython; python_version >= '3' # ipython 6 not compatible with python 2 12 | -------------------------------------------------------------------------------- /altair/utils/_py3k_compat.py: -------------------------------------------------------------------------------- 1 | import six 2 | 3 | 4 | if six.PY2: 5 | import BaseHTTPServer as server 6 | from StringIO import StringIO as IO 7 | else: 8 | from http import server 9 | from io import BytesIO as IO 10 | 11 | 12 | __all__ = ( 13 | "server", 14 | "IO" 15 | ) 16 | -------------------------------------------------------------------------------- /altair/utils/tests/test_server.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test http server 3 | """ 4 | 5 | from altair.utils.server import serve, MockServer 6 | 7 | 8 | def test_serve(): 9 | html = 'Title

Content

' 10 | serve(html, open_browser=False, http_server=MockServer) 11 | -------------------------------------------------------------------------------- /doc/_templates/class.rst: -------------------------------------------------------------------------------- 1 | :mod:`{{module}}`.{{objname}} 2 | {{ underline }}============== 3 | 4 | .. currentmodule:: {{ module }} 5 | 6 | .. autoclass:: {{ objname }} 7 | 8 | {% block methods %} 9 | .. automethod:: __init__ 10 | {% endblock %} 11 | 12 | .. raw:: html 13 | 14 |
15 | -------------------------------------------------------------------------------- /altair/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | __version__ = '2.5.0dev0' 3 | 4 | from .vegalite import * 5 | from . import examples 6 | 7 | def load_ipython_extension(ipython): 8 | from ._magics import vega, vegalite 9 | ipython.register_magic_function(vega, 'cell') 10 | ipython.register_magic_function(vegalite, 'cell') 11 | -------------------------------------------------------------------------------- /altair/utils/urls.py: -------------------------------------------------------------------------------- 1 | D3_JS_URL = "https://d3js.org/d3.v3.min.js" 2 | VEGA_JS_URL = "https://cdnjs.cloudflare.com/ajax/libs/vega/2.6.5/vega.min.js" 3 | VEGALITE_JS_URL = "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/1.2.1/vega-lite.min.js" 4 | VEGAEMBED_JS_URL = "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/2.2.0/vega-embed.min.js" 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = 3 | E # Ignore all PEP8 rules 4 | W # Ignore all whitespace rules 5 | F811 # Ignore variable redefinitions until https://github.com/altair-viz/altair/issues/734 is resolved 6 | 7 | [metadata] 8 | description-file = README.md 9 | license_file = LICENSE 10 | 11 | [bdist_wheel] 12 | universal = 1 -------------------------------------------------------------------------------- /altair/vegalite/display.py: -------------------------------------------------------------------------------- 1 | from ..utils.display import Displayable, default_renderer_base, json_renderer_base 2 | from ..utils.display import RendererRegistry, HTMLRenderer 3 | 4 | 5 | __all__ = ( 6 | "Displayable", 7 | "default_renderer_base", 8 | "json_renderer_base", 9 | "RendererRegistry", 10 | "HTMLRenderer", 11 | ) 12 | -------------------------------------------------------------------------------- /tools/schemapi/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | schemapi: tools for generating Python APIs from JSON schemas 3 | """ 4 | from .schemapi import SchemaBase, Undefined 5 | from .decorator import schemaclass 6 | from .utils import SchemaInfo 7 | 8 | 9 | __all__ = ( 10 | "SchemaBase", 11 | "Undefined", 12 | "schemaclass", 13 | "SchemaInfo" 14 | ) 15 | -------------------------------------------------------------------------------- /altair/examples/strip_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Strip Plot 3 | ----------------- 4 | A simple example of how to make a strip plot. 5 | """ 6 | # category: simple charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.cars() 11 | 12 | alt.Chart(source).mark_tick().encode( 13 | x='Horsepower:Q', 14 | y='Cylinders:O' 15 | ) 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: install 2 | 3 | install: 4 | python setup.py install 5 | 6 | test : 7 | python -m pytest --pyargs --doctest-modules altair 8 | 9 | test-coverage: 10 | python -m pytest --pyargs --doctest-modules --cov=altair --cov-report term altair 11 | 12 | test-coverage-html: 13 | python -m pytest --pyargs --doctest-modules --cov=altair --cov-report html altair 14 | -------------------------------------------------------------------------------- /altair/vega/display.py: -------------------------------------------------------------------------------- 1 | from ..utils.display import Displayable, default_renderer_base, json_renderer_base 2 | from ..utils.display import MimeBundleType, RendererType, HTMLRenderer 3 | 4 | 5 | __all__ = ( 6 | "Displayable", 7 | "default_renderer_base", 8 | "json_renderer_base", 9 | "MimeBundleType", 10 | "RendererType", 11 | "HTMLRenderer", 12 | ) 13 | -------------------------------------------------------------------------------- /altair/examples/bubble_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bubble Plot 3 | ----------------- 4 | This example shows how to make a bubble plot. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.cars() 11 | 12 | alt.Chart(source).mark_point().encode( 13 | x='Horsepower', 14 | y='Miles_per_Gallon', 15 | size='Acceleration' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/grouped_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Grouped Bar Chart 3 | ----------------- 4 | This example shows a grouped bar chart. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='year:O', 14 | y='sum(yield):Q', 15 | color='year:N', 16 | column='site:N' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/trellis_scatter_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Trellis Scatter Plot 3 | ----------------------- 4 | This example shows how to make a trellis scatter plot. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.cars() 11 | 12 | alt.Chart(source).mark_point().encode( 13 | x='Horsepower:Q', 14 | y='Miles_per_Gallon:Q', 15 | row='Origin:N' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/trail_marker.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line Chart with Varying Size 3 | ---------------------------- 4 | This is example of using the ``trail`` marker to vary the size of a line. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | alt.Chart(source).mark_trail().encode( 13 | x='year:T', 14 | y='wheat:Q', 15 | size='wheat:Q' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/layered_area_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Layered Area Chart 3 | ------------------ 4 | This example shows a layered area chart. 5 | """ 6 | # category: area charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source).mark_area(opacity=0.3).encode( 13 | x="year:T", 14 | y=alt.Y("net_generation:Q", stack=None), 15 | color="source:N" 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/trellis_area.py: -------------------------------------------------------------------------------- 1 | """ 2 | Trellis Area Chart 3 | ------------------ 4 | This example shows small multiples of an area chart. 5 | """ 6 | # category: area charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source).mark_area().encode( 13 | x="year:T", 14 | y="net_generation:Q", 15 | color="source:N", 16 | row="source:N" 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_horizontal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Horizontal Bar Chart 3 | -------------------- 4 | This example is a bar chart drawn horizontally by putting the quantitative value on the x axis. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='wheat:Q', 14 | y="year:O" 15 | ).properties(height=700) 16 | -------------------------------------------------------------------------------- /altair/examples/multiple_marks.py: -------------------------------------------------------------------------------- 1 | """ 2 | Multiple Marks 3 | ============== 4 | This example demonstrates creating a single chart with multiple markers 5 | representing the same data. 6 | """ 7 | # category: other charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.stocks() 12 | 13 | alt.Chart(source).mark_line(point=True).encode( 14 | x='date:T', 15 | y='price:Q', 16 | color='symbol:N' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/simple_stacked_area_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Stacked Area Chart 3 | ------------------------- 4 | This example shows how to make a simple stacked area chart. 5 | """ 6 | # category: simple charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source).mark_area().encode( 13 | x="year:T", 14 | y="net_generation:Q", 15 | color="source:N" 16 | ) 17 | -------------------------------------------------------------------------------- /doc/_static/custom.css: -------------------------------------------------------------------------------- 1 | .wy-nav-side p.caption { 2 | color: #F5F5F5; 3 | } 4 | 5 | div.wy-side-nav-search { 6 | background: #757575; 7 | } 8 | 9 | div.wy-side-nay { 10 | background: #212121; 11 | } 12 | 13 | table.field-list td li { 14 | line-height: 18px; 15 | } 16 | 17 | table.docutils td p { 18 | font-size: 14px !important; 19 | margin-bottom: 6px; 20 | 21 | } 22 | 23 | table.docutils td li { 24 | line-height: 18px; 25 | 26 | } -------------------------------------------------------------------------------- /altair/examples/grouped_bar_chart_horizontal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Horizontal Grouped Bar Chart 3 | ---------------------------- 4 | This example shows a horizontal grouped bar chart. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='sum(yield):Q', 14 | y='year:O', 15 | color='year:N', 16 | row='site:N' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/binned_scatterplot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Binned Scatterplot 3 | ------------------ 4 | This example shows how to make a binned scatterplot. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.movies.url 11 | 12 | alt.Chart(source).mark_circle().encode( 13 | alt.X('IMDB_Rating:Q', bin=True), 14 | alt.Y('Rotten_Tomatoes_Rating:Q', bin=True), 15 | size='count()' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/slope_graph.py: -------------------------------------------------------------------------------- 1 | """ 2 | Slope Graph 3 | ----------------------- 4 | This example shows how to make Slope Graph. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_line().encode( 13 | x='year:O', # When using datetime values, ordinal encoding is crucial to get the right look. 14 | y='median(yield)', 15 | color='site' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/vegalite/v1/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .schema import * 3 | from .api import * 4 | 5 | from ...datasets import ( 6 | list_datasets, 7 | load_dataset 8 | ) 9 | 10 | from .. import expr 11 | 12 | from .display import VegaLite, renderers 13 | 14 | from .data import ( 15 | MaxRowsError, 16 | pipe, curry, limit_rows, 17 | sample, to_json, to_csv, to_values, 18 | default_data_transformer, 19 | data_transformers 20 | ) 21 | -------------------------------------------------------------------------------- /altair/examples/layered_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Layered Bar Chart 3 | ----------------- 4 | This example shows a segmented bar chart that is layered rather than stacked. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source).mark_bar(opacity=0.7).encode( 13 | x='year:O', 14 | y=alt.Y('net_generation:Q', stack=None), 15 | color="source", 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/simple_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Bar Chart 3 | ================ 4 | This example shows a basic bar chart created with Altair. 5 | """ 6 | # category: simple charts 7 | import altair as alt 8 | import pandas as pd 9 | 10 | source = pd.DataFrame({ 11 | 'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], 12 | 'b': [28, 55, 43, 91, 81, 53, 19, 87, 52] 13 | }) 14 | 15 | alt.Chart(source).mark_bar().encode( 16 | x='a', 17 | y='b' 18 | ) 19 | -------------------------------------------------------------------------------- /altair/examples/simple_histogram.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Histogram 3 | ---------------- 4 | This example shows how to make a basic histogram, based on the vega-lite docs 5 | https://vega.github.io/vega-lite/examples/histogram.html 6 | """ 7 | # category: simple charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.movies.url 12 | 13 | alt.Chart(source).mark_bar().encode( 14 | alt.X("IMDB_Rating:Q", bin=True), 15 | y='count()', 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/interactive_scatter_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Interactive Colored Scatterplot 3 | -------------------------------------- 4 | This example shows how to make an interactive scatterplot. 5 | """ 6 | # category: interactive charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.cars() 11 | 12 | alt.Chart(source).mark_circle().encode( 13 | x='Horsepower', 14 | y='Miles_per_Gallon', 15 | color='Origin' 16 | ).interactive() 17 | -------------------------------------------------------------------------------- /altair/examples/stacked_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stacked Bar Chart 3 | ----------------- 4 | 5 | This is an example of a stacked bar chart using data which contains crop yields over different regions and different years in the 1930s. 6 | """ 7 | # category: bar charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.barley() 12 | 13 | alt.Chart(source).mark_bar().encode( 14 | x='variety', 15 | y='sum(yield)', 16 | color='site' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/normalized_stacked_area_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Normalized Stacked Area Chart 3 | ----------------------------- 4 | This example shows how to make a normalized stacked area chart. 5 | """ 6 | # category: area charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source).mark_area().encode( 13 | x="year:T", 14 | y=alt.Y("net_generation:Q", stack="normalize"), 15 | color="source:N" 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/table_bubble_plot_github.py: -------------------------------------------------------------------------------- 1 | """ 2 | Table Bubble Plot (Github Punch Card) 3 | ------------------------------------- 4 | This example shows github contributions by the day of week and hour of the day. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.github.url 11 | 12 | alt.Chart(source).mark_circle().encode( 13 | x='hours(time):O', 14 | y='day(time):O', 15 | size='sum(count):Q' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/trellis_histogram.py: -------------------------------------------------------------------------------- 1 | """ 2 | Trellis Histogram 3 | ----------------- 4 | This example shows how to make a basic trellis histogram. 5 | https://vega.github.io/vega-lite/examples/trellis_bar_histogram.html 6 | """ 7 | # category: histograms 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.cars() 12 | 13 | alt.Chart(source).mark_bar().encode( 14 | alt.X("Horsepower:Q", bin=True), 15 | y='count()', 16 | row='Origin' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/line_chart_with_points.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line Chart with Points 3 | ---------------------- 4 | This chart shows a simple line chart with points marking each value. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | import numpy as np 9 | import pandas as pd 10 | 11 | x = np.arange(100) 12 | source = pd.DataFrame({ 13 | 'x': x, 14 | 'f(x)': np.sin(x / 5)} 15 | ) 16 | 17 | alt.Chart(source).mark_line(point=True).encode( 18 | x='x', 19 | y='f(x)' 20 | ) 21 | -------------------------------------------------------------------------------- /altair/examples/simple_line_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Line Chart 3 | ----------------- 4 | This chart shows the most basic line chart, made from a dataframe with two 5 | columns. 6 | """ 7 | # category: simple charts 8 | 9 | import altair as alt 10 | import numpy as np 11 | import pandas as pd 12 | 13 | x = np.arange(100) 14 | source = pd.DataFrame({ 15 | 'x': x, 16 | 'f(x)': np.sin(x / 5)} 17 | ) 18 | 19 | alt.Chart(source).mark_line().encode( 20 | x='x', 21 | y='f(x)' 22 | ) 23 | -------------------------------------------------------------------------------- /altair/vegalite/v2/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | from .schema import * 3 | from .api import * 4 | 5 | from ...datasets import ( 6 | list_datasets, 7 | load_dataset 8 | ) 9 | 10 | from ... import expr 11 | from ...expr import datum 12 | 13 | from .display import VegaLite, renderers 14 | 15 | from .data import ( 16 | MaxRowsError, 17 | pipe, curry, limit_rows, 18 | sample, to_json, to_csv, to_values, 19 | default_data_transformer, 20 | data_transformers 21 | ) 22 | -------------------------------------------------------------------------------- /altair/examples/multi_series_line.py: -------------------------------------------------------------------------------- 1 | """ 2 | Multi Series Line Chart 3 | ----------------------- 4 | 5 | This example shows how to make a multi series line chart of the daily closing stock prices for AAPL, AMZN, GOOG, IBM, and MSFT between 2000 and 2010. 6 | """ 7 | # category: line charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.stocks() 12 | 13 | alt.Chart(source).mark_line().encode( 14 | x='date', 15 | y='price', 16 | color='symbol' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/gantt_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Gantt Chart 3 | ----------------- 4 | This example shows how to make a simple Gantt chart. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | import pandas as pd 9 | 10 | source = pd.DataFrame([ 11 | {"task": "A", "start": 1, "end": 3}, 12 | {"task": "B", "start": 3, "end": 8}, 13 | {"task": "C", "start": 8, "end": 10} 14 | ]) 15 | 16 | alt.Chart(source).mark_bar().encode( 17 | x='start', 18 | x2='end', 19 | y='task' 20 | ) 21 | -------------------------------------------------------------------------------- /altair/examples/horizontal_stacked_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Horizontal Stacked Bar Chart 3 | ============================ 4 | This is an example of a horizontal stacked bar chart using data which contains crop yields over different regions and different years in the 1930s. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='sum(yield)', 14 | y='variety', 15 | color='site' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/vegalite/v1/html.py: -------------------------------------------------------------------------------- 1 | HTML_TEMPLATE = """ 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 16 | 17 | 18 | """ 19 | -------------------------------------------------------------------------------- /altair/vegalite/v2/html.py: -------------------------------------------------------------------------------- 1 | HTML_TEMPLATE = """ 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 16 | 17 | 18 | """ 19 | -------------------------------------------------------------------------------- /altair/examples/line_percent.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line Chart with Percent axis 3 | ---------------------------- 4 | This example shows how to format the tick labels of the y-axis of a chart as percentages. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.jobs.url 11 | 12 | alt.Chart(source).mark_line().encode( 13 | alt.X('year:O'), 14 | alt.Y('perc:Q', axis=alt.Axis(format='%')), 15 | color='sex:N' 16 | ).transform_filter( 17 | alt.datum.job == 'Welder' 18 | ) 19 | -------------------------------------------------------------------------------- /altair/examples/binned_heatmap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Binned Heatmap 3 | -------------- 4 | This example shows how to make a heatmap from binned quantitative data. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.movies.url 11 | 12 | alt.Chart(source).mark_rect().encode( 13 | alt.X('IMDB_Rating:Q', bin=alt.Bin(maxbins=60)), 14 | alt.Y('Rotten_Tomatoes_Rating:Q', bin=alt.Bin(maxbins=40)), 15 | alt.Color('count(IMDB_Rating):Q', scale=alt.Scale(scheme='greenblue')) 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/normalized_stacked_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Normalized Stacked Bar Chart 3 | ---------------------------- 4 | This is an example of a normalized stacked bar chart using data which contains crop yields over different regions and different years in the 1930s. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x=alt.X('sum(yield)', stack="normalize"), 14 | y='variety', 15 | color='site' 16 | ) 17 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_with_mean_line.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Line at Mean 3 | --------------------------- 4 | This example shows the mean value overlayed on a bar chart. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | bar = alt.Chart(source).mark_bar().encode( 13 | x='year:O', 14 | y='wheat:Q' 15 | ) 16 | 17 | rule = alt.Chart(source).mark_rule(color='red').encode( 18 | y='mean(wheat):Q' 19 | ) 20 | 21 | (bar + rule).properties(width=600) 22 | -------------------------------------------------------------------------------- /altair/examples/bar_and_line_with_dual_axis.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Line on Dual Axis 3 | -------------------------------- 4 | This example shows how to combine two plots and keep their axes. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | base = alt.Chart(source).encode(x='year:O') 13 | 14 | bar = base.mark_bar().encode(y='wheat:Q') 15 | 16 | line = base.mark_line(color='red').encode( 17 | y='wages:Q' 18 | ) 19 | 20 | (bar + line).properties(width=600) 21 | -------------------------------------------------------------------------------- /altair/examples/filled_step_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Filled Step Chart 3 | ----------------- 4 | This example shows Google's stock price over time as a step chart with its area filled in and its line emphasized. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.stocks() 11 | 12 | alt.Chart(source).mark_area( 13 | color="lightblue", 14 | interpolate='step-after', 15 | line=True 16 | ).encode( 17 | x='date', 18 | y='price' 19 | ).transform_filter(alt.datum.symbol == 'GOOG') 20 | -------------------------------------------------------------------------------- /altair/examples/trellis_stacked_bar_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Trellis Stacked Bar Chart 3 | ========================= 4 | This is an example of a horizontal stacked bar chart using data which contains crop yields over different regions and different years in the 1930s. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | column='year', 14 | x='sum(yield)', 15 | y='variety', 16 | color='site' 17 | ).properties(width=250) 18 | -------------------------------------------------------------------------------- /altair/examples/multifeature_scatter_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Multifeature Scatter Plot 3 | ========================= 4 | This example shows how to make a scatter plot with multiple feature encodings. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iris() 11 | 12 | alt.Chart(source).mark_circle().encode( 13 | alt.X('sepalLength', scale=alt.Scale(zero=False)), 14 | alt.Y('sepalWidth', scale=alt.Scale(zero=False, padding=1)), 15 | color='species', 16 | size='petalWidth' 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/choropleth.py: -------------------------------------------------------------------------------- 1 | """ 2 | Choropleth Map 3 | ============== 4 | A choropleth map of unemployment rate per county in the US 5 | """ 6 | # category: maps 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | counties = alt.topo_feature(data.us_10m.url, 'counties') 11 | source = data.unemployment.url 12 | 13 | alt.Chart(counties).mark_geoshape().encode( 14 | color='rate:Q' 15 | ).transform_lookup( 16 | lookup='id', 17 | from_=alt.LookupData(source, 'id', ['rate']) 18 | ).project( 19 | type='albersUsa' 20 | ).properties( 21 | width=500, 22 | height=300 23 | ) 24 | -------------------------------------------------------------------------------- /altair/vega/v2/data.py: -------------------------------------------------------------------------------- 1 | from ..data import (MaxRowsError, curry, default_data_transformer, limit_rows, 2 | pipe, sample, to_csv, to_json, to_values) 3 | 4 | 5 | # ============================================================================== 6 | # Vega 2 data transformers 7 | # ============================================================================== 8 | 9 | 10 | __all__ = ( 11 | 'MaxRowsError', 12 | 'curry', 13 | 'default_data_transformer', 14 | 'limit_rows', 15 | 'pipe', 16 | 'sample', 17 | 'to_csv', 18 | 'to_json', 19 | 'to_values', 20 | ) 21 | -------------------------------------------------------------------------------- /altair/vega/v3/data.py: -------------------------------------------------------------------------------- 1 | from ..data import (MaxRowsError, curry, default_data_transformer, limit_rows, 2 | pipe, sample, to_csv, to_json, to_values) 3 | 4 | 5 | # ============================================================================== 6 | # Vega 3 data transformers 7 | # ============================================================================== 8 | 9 | 10 | __all__ = ( 11 | 'MaxRowsError', 12 | 'curry', 13 | 'default_data_transformer', 14 | 'limit_rows', 15 | 'pipe', 16 | 'sample', 17 | 'to_csv', 18 | 'to_json', 19 | 'to_values', 20 | ) 21 | -------------------------------------------------------------------------------- /altair/vega/v4/data.py: -------------------------------------------------------------------------------- 1 | from ..data import (MaxRowsError, curry, default_data_transformer, limit_rows, 2 | pipe, sample, to_csv, to_json, to_values) 3 | 4 | 5 | # ============================================================================== 6 | # Vega 3 data transformers 7 | # ============================================================================== 8 | 9 | 10 | __all__ = ( 11 | 'MaxRowsError', 12 | 'curry', 13 | 'default_data_transformer', 14 | 'limit_rows', 15 | 'pipe', 16 | 'sample', 17 | 'to_csv', 18 | 'to_json', 19 | 'to_values', 20 | ) 21 | -------------------------------------------------------------------------------- /altair/vegalite/v1/theme.py: -------------------------------------------------------------------------------- 1 | """Tools for enabling and registering chart themes""" 2 | 3 | from ...utils.theme import ThemeRegistry 4 | 5 | # The entry point group that can be used by other packages to declare other 6 | # renderers that will be auto-detected. Explicit registration is also 7 | # allowed by the PluginRegistery API. 8 | ENTRY_POINT_GROUP = 'altair.vegalite.v1.theme' # type: str 9 | 10 | themes = ThemeRegistry(entry_point_group=ENTRY_POINT_GROUP) 11 | 12 | themes.register('default', lambda: {"width": 400, "height": 300}) 13 | themes.register('none', lambda: {}) 14 | themes.enable('default') 15 | -------------------------------------------------------------------------------- /altair/examples/stacked_bar_chart_sorted_segments.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stacked Bar Chart with Sorted Segments 3 | -------------------------------------- 4 | This is an example of a stacked-bar chart with the segments of each bar resorted. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='sum(yield)', 14 | y='variety', 15 | color='site', 16 | order=alt.Order( 17 | # Sort the segments of the bars by this field 18 | 'site', 19 | sort='ascending' 20 | ) 21 | ) 22 | -------------------------------------------------------------------------------- /altair/examples/streamgraph.py: -------------------------------------------------------------------------------- 1 | """ 2 | Streamgraph 3 | ----------------- 4 | This example shows the streamgraph from vega-lite examples. 5 | """ 6 | # category: area charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.unemployment_across_industries.url 11 | 12 | alt.Chart(source).mark_area().encode( 13 | alt.X('yearmonth(date):T', 14 | axis=alt.Axis(format='%Y', domain=False, tickSize=0) 15 | ), 16 | alt.Y('sum(count):Q', stack='center', axis=None), 17 | alt.Color('series:N', 18 | scale=alt.Scale(scheme='category20b') 19 | ) 20 | ).interactive() 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | cache: pip 4 | 5 | # Enable 3.7 without globally enabling sudo and xenial 6 | matrix: 7 | include: 8 | - python: 2.7 9 | - python: 3.5 10 | - python: 3.6 11 | - python: 3.7 12 | dist: xenial 13 | sudo: true 14 | 15 | env: 16 | global: 17 | - TEST_DIR=/tmp/_altair/ 18 | 19 | before_install: 20 | - pip install pip --upgrade; 21 | - pip install -U pytest; 22 | 23 | install: 24 | - pip install -e .[dev]; 25 | 26 | script: 27 | - flake8 ./; 28 | - mkdir -p $TEST_DIR 29 | - cd $TEST_DIR && python -m pytest --pyargs --doctest-modules altair; 30 | -------------------------------------------------------------------------------- /altair/examples/histogram_with_a_global_mean_overlay.py: -------------------------------------------------------------------------------- 1 | """ 2 | Histogram with a Global Mean Overlay 3 | ------------------------------------ 4 | This example shows a histogram with a global mean overlay. 5 | """ 6 | # category: histograms 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.movies.url 11 | 12 | base = alt.Chart(source) 13 | 14 | bar = base.mark_bar().encode( 15 | x=alt.X('IMDB_Rating:Q', bin=True, axis=None), 16 | y='count()' 17 | ) 18 | 19 | rule = base.mark_rule(color='red').encode( 20 | x='mean(IMDB_Rating):Q', 21 | size=alt.value(5) 22 | ) 23 | 24 | bar + rule 25 | -------------------------------------------------------------------------------- /altair/examples/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def iter_examples(): 5 | """Iterate over the examples in this directory. 6 | 7 | Each item is a dict with the following keys: 8 | - "name" : the unique name of the example 9 | - "filename" : the full file path to the example 10 | """ 11 | example_dir = os.path.abspath(os.path.dirname(__file__)) 12 | for filename in os.listdir(example_dir): 13 | name, ext = os.path.splitext(filename) 14 | if name.startswith('_') or ext != '.py': 15 | continue 16 | yield {'name': name, 17 | 'filename': os.path.join(example_dir, filename)} 18 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_with_negatives.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Negative Values 3 | ============================== 4 | This example shows a bar chart with both positive and negative values. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.us_employment() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x="month:T", 14 | y="nonfarm_change:Q", 15 | color=alt.condition( 16 | alt.datum.nonfarm_change > 0, 17 | alt.value("steelblue"), # The positive color 18 | alt.value("orange") # The negative color 19 | ) 20 | ).properties(width=600) 21 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_with_labels.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Labels 3 | ===================== 4 | This example shows a basic horizontal bar chart with labels created with Altair. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | bars = alt.Chart(source).mark_bar().encode( 13 | x='wheat:Q', 14 | y="year:O" 15 | ) 16 | 17 | text = bars.mark_text( 18 | align='left', 19 | baseline='middle', 20 | dx=3 # Nudges text to right so it doesn't appear on top of the bar 21 | ).encode( 22 | text='wheat:Q' 23 | ) 24 | 25 | (bars + text).properties(height=900) 26 | -------------------------------------------------------------------------------- /altair/examples/interactive_brush.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interactive Rectangular Brush 3 | ============================= 4 | This example shows how to add a simple rectangular brush to a scatter plot. 5 | By clicking and dragging on the plot, you can highlight points within the 6 | range. 7 | """ 8 | # category: interactive charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.cars() 13 | brush = alt.selection(type='interval') 14 | 15 | alt.Chart(source).mark_point().encode( 16 | x='Horsepower:Q', 17 | y='Miles_per_Gallon:Q', 18 | color=alt.condition(brush, 'Cylinders:O', alt.value('grey')) 19 | ).add_selection(brush) 20 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_sorted.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sorted Bar Chart 3 | ================ 4 | This example shows a bar chart sorted by a calculated value. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='sum(yield):Q', 14 | y=alt.Y( 15 | 'site:N', 16 | sort=alt.EncodingSortField( 17 | field="yield", # The field to use for the sort 18 | op="sum", # The operation to run on the field prior to sorting 19 | order="descending" # The order to sort in 20 | ) 21 | ) 22 | ) 23 | -------------------------------------------------------------------------------- /altair/examples/scatter_tooltips.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Scatter Plot with Tooltips 3 | --------------------------------- 4 | A scatter plot of the cars dataset, with tooltips showing selected column 5 | values when you hover over points. We make the points larger so that it is 6 | easier to hover over them. 7 | """ 8 | # category: simple charts 9 | 10 | import altair as alt 11 | from vega_datasets import data 12 | 13 | source = data.cars() 14 | 15 | alt.Chart(source).mark_circle(size=60).encode( 16 | x='Horsepower', 17 | y='Miles_per_Gallon', 18 | color='Origin', 19 | tooltip=['Name', 'Origin', 'Horsepower', 'Miles_per_Gallon'] 20 | ).interactive() 21 | -------------------------------------------------------------------------------- /altair/examples/trellis_area_sort_array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Trellis Area Sort Chart 3 | ----------------------- 4 | This example shows small multiples of an area chart. 5 | Stock prices of four large companies 6 | sorted by `['MSFT', 'AAPL', 'IBM', 'AMZN']` 7 | ''' 8 | # category: area charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.stocks() 13 | 14 | alt.Chart(source).transform_filter( 15 | alt.datum.symbol != 'GOOG' 16 | ).mark_area().encode( 17 | x='date:T', 18 | y='price:Q', 19 | color='symbol:N', 20 | row=alt.Row('symbol:N', sort=['MSFT', 'AAPL', 'IBM', 'AMZN']) 21 | ).properties(height=50, width=400) 22 | -------------------------------------------------------------------------------- /altair/examples/simple_heatmap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Heatmap 3 | -------------- 4 | This example shows a simple heatmap for showing gridded data. 5 | """ 6 | # category: simple charts 7 | import altair as alt 8 | import numpy as np 9 | import pandas as pd 10 | 11 | # Compute x^2 + y^2 across a 2D grid 12 | x, y = np.meshgrid(range(-5, 5), range(-5, 5)) 13 | z = x ** 2 + y ** 2 14 | 15 | # Convert this grid to columnar data expected by Altair 16 | source = pd.DataFrame({'x': x.ravel(), 17 | 'y': y.ravel(), 18 | 'z': z.ravel()}) 19 | 20 | alt.Chart(source).mark_rect().encode( 21 | x='x:O', 22 | y='y:O', 23 | color='z:Q' 24 | ) 25 | -------------------------------------------------------------------------------- /altair/examples/scatter_with_labels.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Scatter Plot with Labels 3 | =============================== 4 | This example shows a basic scatter plot with labels created with Altair. 5 | """ 6 | # category: scatter plots 7 | import altair as alt 8 | import pandas as pd 9 | 10 | source = pd.DataFrame({ 11 | 'x': [1, 3, 5, 7, 9], 12 | 'y': [1, 3, 5, 7, 9], 13 | 'label': ['A', 'B', 'C', 'D', 'E'] 14 | }) 15 | 16 | bars = alt.Chart(source).mark_point().encode( 17 | x='x:Q', 18 | y='y:Q' 19 | ) 20 | 21 | text = bars.mark_text( 22 | align='left', 23 | baseline='middle', 24 | dx=7 25 | ).encode( 26 | text='label' 27 | ) 28 | 29 | bars + text 30 | -------------------------------------------------------------------------------- /altair/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .core import ( 2 | infer_vegalite_type, 3 | sanitize_dataframe, 4 | parse_shorthand, 5 | use_signature, 6 | update_subtraits, 7 | update_nested, 8 | display_traceback, 9 | SchemaBase, 10 | Undefined 11 | ) 12 | from .html import spec_to_html 13 | from .plugin_registry import PluginRegistry 14 | 15 | 16 | __all__ = ( 17 | 'infer_vegalite_type', 18 | 'sanitize_dataframe', 19 | 'spec_to_html', 20 | 'parse_shorthand', 21 | 'use_signature', 22 | 'update_subtraits', 23 | 'update_nested', 24 | 'display_traceback', 25 | 'SchemaBase', 26 | 'Undefined', 27 | 'PluginRegistry' 28 | ) 29 | -------------------------------------------------------------------------------- /altair/utils/tests/test_execeval.py: -------------------------------------------------------------------------------- 1 | from ..execeval import eval_block 2 | 3 | HAS_RETURN = """ 4 | x = 4 5 | y = 2 * x 6 | 3 * y 7 | """ 8 | 9 | NO_RETURN = """ 10 | x = 4 11 | y = 2 * x 12 | z = 3 * y 13 | """ 14 | 15 | 16 | def test_eval_block_with_return(): 17 | _globals = {} 18 | result = eval_block(HAS_RETURN, _globals) 19 | assert result == 24 20 | assert _globals['x'] == 4 21 | assert _globals['y'] == 8 22 | 23 | 24 | 25 | def test_eval_block_without_return(): 26 | _globals = {} 27 | result = eval_block(NO_RETURN, _globals) 28 | assert result is None 29 | assert _globals['x'] == 4 30 | assert _globals['y'] == 8 31 | assert _globals['z'] == 24 32 | -------------------------------------------------------------------------------- /doc/sync_website.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get git hash for commit message 4 | GITHASH=$(git rev-parse HEAD) 5 | MSG="doc build for commit $GITHASH" 6 | cd _build 7 | 8 | # clone the repo if needed 9 | if test -d altair-viz.github.io; 10 | then echo "using existing cloned altair directory"; 11 | else git clone git@github.com:altair-viz/altair-viz.github.io.git; 12 | fi 13 | 14 | # sync the website 15 | cd altair-viz.github.io 16 | git pull 17 | 18 | # remove all tracked files 19 | git ls-files -z | xargs -0 rm -f 20 | 21 | # sync files from html build 22 | rsync -r ../html/ ./ 23 | 24 | # add commit, and push to github 25 | git add . --all 26 | git commit -m "$MSG" 27 | git push origin master 28 | -------------------------------------------------------------------------------- /altair/examples/one_dot_per_zipcode.py: -------------------------------------------------------------------------------- 1 | """ 2 | One Dot Per Zipcode 3 | ----------------------- 4 | This example shows a geographical plot with one dot per zipcode. 5 | """ 6 | # category: case studies 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | # Since the data is more than 5,000 rows we'll import it from a URL 11 | source = data.zipcodes.url 12 | 13 | alt.Chart(source).mark_circle(size=3).encode( 14 | longitude='longitude:Q', 15 | latitude='latitude:Q', 16 | color='digit:N' 17 | ).project( 18 | type='albersUsa' 19 | ).properties( 20 | width=650, 21 | height=400 22 | ).transform_calculate( 23 | "digit", alt.expr.substring(alt.datum.zip_code, 0, 1) 24 | ) 25 | -------------------------------------------------------------------------------- /altair/examples/scatter_href.py: -------------------------------------------------------------------------------- 1 | """ 2 | Scatter Plot with Href 3 | ---------------------- 4 | This example shows a scatter plot with an ``href`` encoding constructed from 5 | the car name. With this encoding, you can click on any of the points to open 6 | a google search for the car name. 7 | """ 8 | # category: scatter plots 9 | 10 | import altair as alt 11 | from vega_datasets import data 12 | 13 | source = data.cars() 14 | 15 | alt.Chart(source).transform_calculate( 16 | url='https://www.google.com/search?q=' + alt.datum.Name 17 | ).mark_point().encode( 18 | x='Horsepower:Q', 19 | y='Miles_per_Gallon:Q', 20 | color='Origin:N', 21 | href='url:N', 22 | tooltip=['Name:N', 'url:N'] 23 | ) 24 | -------------------------------------------------------------------------------- /altair/datasets.py: -------------------------------------------------------------------------------- 1 | """Datasets for use with Altair 2 | 3 | The functions here are merely thin wrappers for data access routines in the 4 | vega_datasets package. 5 | """ 6 | import warnings 7 | 8 | MSG = ("load_dataset is deprecated. " 9 | "Please use the vega_datasets package instead.") 10 | 11 | 12 | def load_dataset(name): 13 | """Load a dataset by name as a pandas.DataFrame.""" 14 | warnings.warn(MSG, DeprecationWarning) 15 | import vega_datasets 16 | return vega_datasets.data(name) 17 | 18 | 19 | def list_datasets(): 20 | """List the available datasets.""" 21 | warnings.warn(MSG, DeprecationWarning) 22 | import vega_datasets 23 | return vega_datasets.data.list_datasets() 24 | -------------------------------------------------------------------------------- /altair/examples/step_chart.py: -------------------------------------------------------------------------------- 1 | """ 2 | Step Chart 3 | ---------- 4 | This example shows Google's stock price over time. 5 | This uses the "step-after" interpolation scheme. 6 | The full list of interpolation options includes 'linear', 7 | 'linear-closed', 'step', 'step-before', 'step-after', 'basis', 8 | 'basis-open', 'basis-closed', 'cardinal', 'cardinal-open', 9 | 'cardinal-closed', 'bundle', and 'monotone'. 10 | """ 11 | # category: line charts 12 | import altair as alt 13 | from vega_datasets import data 14 | 15 | source = data.stocks() 16 | 17 | alt.Chart(source).mark_line(interpolate='step-after').encode( 18 | x='date', 19 | y='price' 20 | ).transform_filter( 21 | alt.datum.symbol == 'GOOG' 22 | ) 23 | -------------------------------------------------------------------------------- /altair/examples/scatter_matrix.py: -------------------------------------------------------------------------------- 1 | """ 2 | Scatter Matrix 3 | -------------- 4 | An example of using a RepeatChart to construct a multi-panel scatter plot 5 | with linked panning and zooming. 6 | """ 7 | # category: scatter plots 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.cars() 12 | 13 | alt.Chart(source).mark_circle().encode( 14 | alt.X(alt.repeat("column"), type='quantitative'), 15 | alt.Y(alt.repeat("row"), type='quantitative'), 16 | color='Origin:N' 17 | ).properties( 18 | width=150, 19 | height=150 20 | ).repeat( 21 | row=['Horsepower', 'Acceleration', 'Miles_per_Gallon'], 22 | column=['Miles_per_Gallon', 'Acceleration', 'Horsepower'] 23 | ).interactive() 24 | -------------------------------------------------------------------------------- /altair/examples/anscombe_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Anscombe's Quartet 3 | ------------------ 4 | 5 | This example shows how to use the column channel to make a trellis plot. Anscombe's Quartet is a famous dataset constructed by Francis Anscombe. Common summary statistics are identical for each subset of the data, despite the subsets having vastly different characteristics. 6 | """ 7 | # category: case studies 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.anscombe() 12 | 13 | alt.Chart(source).mark_circle().encode( 14 | alt.X('X', scale=alt.Scale(zero=False)), 15 | alt.Y('Y', scale=alt.Scale(zero=False)), 16 | column='Series' 17 | ).properties( 18 | width=150, 19 | height=150 20 | ) 21 | -------------------------------------------------------------------------------- /altair/vegalite/data.py: -------------------------------------------------------------------------------- 1 | 2 | from toolz.curried import curry, pipe 3 | from ..utils.core import sanitize_dataframe 4 | from ..utils.data import ( 5 | MaxRowsError, limit_rows, sample, to_csv, to_json, to_values, 6 | check_data_type, DataTransformerRegistry 7 | ) 8 | 9 | 10 | @curry 11 | def default_data_transformer(data, max_rows=5000): 12 | return pipe(data, limit_rows(max_rows=max_rows), to_values) 13 | 14 | 15 | __all__ = ( 16 | 'DataTransformerRegistry', 17 | 'MaxRowsError', 18 | 'curry', 19 | 'sanitize_dataframe', 20 | 'default_data_transformer', 21 | 'limit_rows', 22 | 'pipe', 23 | 'sample', 24 | 'to_csv', 25 | 'to_json', 26 | 'to_values', 27 | 'check_data_type' 28 | ) 29 | -------------------------------------------------------------------------------- /doc/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | @media screen and (min-width: 767px) { 3 | 4 | .wy-table-responsive table td { 5 | /* !important prevents the common CSS stylesheets from overriding 6 | this as on RTD they are loaded after this stylesheet */ 7 | white-space: normal !important; 8 | } 9 | .wy-table-responsive { 10 | overflow: visible !important; 11 | } 12 | } 13 | 14 | .rst-content dl:not(.docutils) dt em { 15 | font-style: normal !important; 16 | line-height: 1.4em !important; 17 | } 18 | 19 | .rst-content div[class^='highlight'] { 20 | background: #fff !important; 21 | } 22 | 23 | img.logo { 24 | width: 120px !important; 25 | } 26 | -------------------------------------------------------------------------------- /altair/examples/gapminder_bubble_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Gapminder Bubble Plot 3 | ===================== 4 | This example shows how to make a bubble plot showing the correlation between 5 | health and income for 187 countries in the world (modified from an example 6 | in Lisa Charlotte Rost's blog post `'One Chart, Twelve Charting Libraries' `_. 7 | """ 8 | # category: case studies 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.gapminder_health_income.url 13 | 14 | alt.Chart(source).mark_circle().encode( 15 | alt.X('income:Q', scale=alt.Scale(type='log')), 16 | alt.Y('health:Q', scale=alt.Scale(zero=False)), 17 | size='population:Q' 18 | ) 19 | -------------------------------------------------------------------------------- /altair/examples/percentage_of_total.py: -------------------------------------------------------------------------------- 1 | """ 2 | Calculating Percentage of Total 3 | ------------------------------- 4 | This chart demonstrates how to use a window transform to display data values 5 | as a percentage of total values. 6 | """ 7 | # category: bar charts 8 | import altair as alt 9 | import pandas as pd 10 | 11 | source = pd.DataFrame({'Activity': ['Sleeping', 'Eating', 'TV', 'Work', 'Exercise'], 12 | 'Time': [8, 2, 4, 8, 2]}) 13 | 14 | alt.Chart(source).mark_bar().encode( 15 | alt.X('PercentOfTotal:Q', axis=alt.Axis(format='.0%')), 16 | y='Activity:N' 17 | ).transform_window( 18 | TotalTime='sum(Time)', 19 | frame=[None, None] 20 | ).transform_calculate( 21 | PercentOfTotal="datum.Time / datum.TotalTime" 22 | ) 23 | -------------------------------------------------------------------------------- /altair/examples/interval_selection.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interval Selection Example 3 | ========================== 4 | 5 | This is an example of creating a stacked chart for which the domain of the 6 | top chart can be selected by interacting with the bottom chart. 7 | """ 8 | # category: area charts 9 | 10 | import altair as alt 11 | from vega_datasets import data 12 | 13 | source = data.sp500.url 14 | 15 | brush = alt.selection(type='interval', encodings=['x']) 16 | 17 | upper = alt.Chart().mark_area().encode( 18 | alt.X('date:T', scale={'domain': brush.ref()}), 19 | y='price:Q' 20 | ).properties( 21 | width=600, 22 | height=200 23 | ) 24 | 25 | lower = upper.properties( 26 | height=60 27 | ).add_selection(brush) 28 | 29 | alt.vconcat(upper, lower, data=source) 30 | -------------------------------------------------------------------------------- /altair/examples/layer_line_color_rule.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line Chart with Layered Aggregates 3 | ---------------------------------- 4 | This example shows how to make a multi-series line chart of the daily closing 5 | stock prices for AAPL, AMZN, GOOG, IBM, and MSFT between 2000 and 2010, along 6 | with a layered rule showing the average values. 7 | """ 8 | # category: line charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.stocks() 13 | 14 | base = alt.Chart(source).properties(width=600) 15 | 16 | line = base.mark_line().encode( 17 | x='date', 18 | y='price', 19 | color='symbol' 20 | ) 21 | 22 | rule = base.mark_rule().encode( 23 | y='average(price)', 24 | color='symbol', 25 | size=alt.value(2) 26 | ) 27 | 28 | line + rule 29 | -------------------------------------------------------------------------------- /altair/examples/scatter_linked_brush.py: -------------------------------------------------------------------------------- 1 | """ 2 | Multi-panel Scatter Plot with Linked Brushing 3 | --------------------------------------------- 4 | This is an example of using an interval selection to control the color of 5 | points across multiple panels. 6 | """ 7 | # category: interactive charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.cars() 12 | 13 | brush = alt.selection(type='interval', resolve='global') 14 | 15 | base = alt.Chart(source).mark_point().encode( 16 | y='Miles_per_Gallon', 17 | color=alt.condition(brush, 'Origin', alt.ColorValue('gray')) 18 | ).add_selection( 19 | brush 20 | ).properties( 21 | width=250, 22 | height=250 23 | ) 24 | 25 | base.encode(x='Horsepower') | base.encode(x='Acceleration') 26 | -------------------------------------------------------------------------------- /altair/examples/tests/test_examples.py: -------------------------------------------------------------------------------- 1 | import pkgutil 2 | 3 | import pytest 4 | 5 | from altair.utils.execeval import eval_block 6 | from altair import examples 7 | 8 | 9 | def iter_example_filenames(): 10 | for importer, modname, ispkg in pkgutil.iter_modules(examples.__path__): 11 | if ispkg or modname.startswith('_'): 12 | continue 13 | yield modname + '.py' 14 | 15 | 16 | @pytest.mark.parametrize('filename', iter_example_filenames()) 17 | def test_examples(filename): 18 | source = pkgutil.get_data(examples.__name__, filename) 19 | chart = eval_block(source) 20 | 21 | if chart is None: 22 | raise ValueError("Example file should define chart in its final " 23 | "statement.") 24 | chart.to_dict() 25 | -------------------------------------------------------------------------------- /altair/vegalite/v2/theme.py: -------------------------------------------------------------------------------- 1 | """Tools for enabling and registering chart themes""" 2 | 3 | from ...utils.theme import ThemeRegistry 4 | 5 | # The entry point group that can be used by other packages to declare other 6 | # renderers that will be auto-detected. Explicit registration is also 7 | # allowed by the PluginRegistery API. 8 | ENTRY_POINT_GROUP = 'altair.vegalite.v2.theme' # type: str 9 | themes = ThemeRegistry(entry_point_group=ENTRY_POINT_GROUP) 10 | 11 | themes.register('default', lambda: {"config": {"view": {"width": 400, "height": 300}}}) 12 | themes.register('opaque', lambda: {"config": {"background": "white", 13 | "view": {"width": 400, "height": 300}}}) 14 | themes.register('none', lambda: {}) 15 | themes.enable('default') 16 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_with_highlighted_bar.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Highlighted Bar 3 | ------------------------------ 4 | This example shows a basic bar chart with a single bar highlighted. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | 12 | alt.Chart(source).mark_bar().encode( 13 | x='year:O', 14 | y="wheat:Q", 15 | # The highlight will be set on the result of a conditional statement 16 | color=alt.condition( 17 | alt.datum.year == 1810, # If the year is 1810 this test returns True, 18 | alt.value('orange'), # which sets the bar orange. 19 | alt.value('steelblue') # And if it's not true it sets the bar steelblue. 20 | ) 21 | ).properties(width=600) 22 | -------------------------------------------------------------------------------- /altair/examples/cumulative_wiki_donations.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cumulative Wikipedia Donations 3 | ============================== 4 | 5 | This chart shows cumulative donations to Wikipedia over the past 10 years. Inspired by this `Reddit post `_ but using lines instead of areas. 6 | """ 7 | # category: case studies 8 | import altair as alt 9 | 10 | source = "https://frdata.wikimedia.org/donationdata-vs-day.csv" 11 | 12 | alt.Chart(source).mark_line().encode( 13 | alt.X('monthdate(date):T', title='Month', axis=alt.Axis(format='%B')), 14 | alt.Y('max(ytdsum):Q', title='Cumulative Donations', stack=None), 15 | alt.Color('year(date):O', legend=alt.Legend(title='Year')), 16 | alt.Order('year(data):O') 17 | ) 18 | -------------------------------------------------------------------------------- /altair/examples/line_with_ci.py: -------------------------------------------------------------------------------- 1 | """ 2 | Line Chart with Confidence Interval Band 3 | ======================================== 4 | How to make a line chart with a bootstrapped 95% confidence interval band. 5 | """ 6 | # category: line charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.cars() 11 | 12 | # Configure the base chart 13 | base = alt.Chart(source) 14 | 15 | # Configure the line 16 | line = base.mark_line().encode( 17 | x='Year', 18 | y='mean(Miles_per_Gallon)' 19 | ) 20 | 21 | # Configure the confidence interval 22 | confidence_interval = base.mark_area(opacity=0.3).encode( 23 | x='Year', 24 | y=alt.Y('ci0(Miles_per_Gallon)', title='Miles/Gallon'), 25 | y2='ci1(Miles_per_Gallon)' 26 | ) 27 | 28 | # Draw the chart 29 | confidence_interval + line 30 | -------------------------------------------------------------------------------- /altair/examples/iowa_electricity.py: -------------------------------------------------------------------------------- 1 | """ 2 | Iowa's renewable energy boom 3 | ---------------------------- 4 | This example is a fully developed stacked chart using the sample dataset of Iowa's electricity sources. 5 | """ 6 | # category: case studies 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.iowa_electricity() 11 | 12 | alt.Chart(source, title="Iowa's renewable energy boom").mark_area().encode( 13 | x=alt.X( 14 | "year:T", 15 | title="Year" 16 | ), 17 | y=alt.Y( 18 | "net_generation:Q", 19 | stack="normalize", 20 | title="Share of net generation", 21 | axis=alt.Axis(format=".0%"), 22 | ), 23 | color=alt.Color( 24 | "source:N", 25 | legend=alt.Legend(title="Electricity source"), 26 | ) 27 | ) 28 | -------------------------------------------------------------------------------- /altair/examples/connected_scatterplot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Connected Scatterplot (Lines with Custom Paths) 3 | ----------------------------------------------- 4 | 5 | This example show how the order encoding can be used to draw a custom path. The dataset tracks miles driven per capita along with gas prices annually from 1956 to 2010. 6 | It is based on Hannah Fairfield's article 'Driving Shifts Into Reverse'. See https://archive.nytimes.com/www.nytimes.com/imagepages/2010/05/02/business/02metrics.html for the original. 7 | """ 8 | # category: scatter plots 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.driving() 13 | 14 | alt.Chart(source).mark_line(point=True).encode( 15 | alt.X('miles', scale=alt.Scale(zero=False)), 16 | alt.Y('gas', scale=alt.Scale(zero=False)), 17 | order='year' 18 | ) 19 | -------------------------------------------------------------------------------- /altair/examples/natural_disasters.py: -------------------------------------------------------------------------------- 1 | """ 2 | Natural Disasters 3 | ----------------- 4 | This example shows a visualization of global deaths from natural disasters. 5 | """ 6 | # category: case studies 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.disasters.url 11 | 12 | alt.Chart(source).mark_circle( 13 | opacity=0.8, 14 | stroke='black', 15 | strokeWidth=1 16 | ).encode( 17 | alt.X('Year:O', axis=alt.Axis(labelAngle=0)), 18 | alt.Y('Entity:N'), 19 | alt.Size('Deaths:Q', 20 | scale=alt.Scale(range=[0, 5000]), 21 | legend=alt.Legend(title='Annual Global Deaths') 22 | ), 23 | alt.Color('Entity:N', legend=None) 24 | ).properties( 25 | width=480, 26 | height=350 27 | ).transform_filter( 28 | alt.datum.Entity != 'All natural disasters' 29 | ) 30 | -------------------------------------------------------------------------------- /altair/examples/choropleth_repeat.py: -------------------------------------------------------------------------------- 1 | """ 2 | Repeated Choropleth Map 3 | ======================= 4 | Three choropleths representing disjoint data from the same table. 5 | """ 6 | # category: maps 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | states = alt.topo_feature(data.us_10m.url, 'states') 11 | source = data.population_engineers_hurricanes.url 12 | variable_list = ['population', 'engineers', 'hurricanes'] 13 | 14 | alt.Chart(states).mark_geoshape().encode( 15 | alt.Color(alt.repeat('row'), type='quantitative') 16 | ).transform_lookup( 17 | lookup='id', 18 | from_=alt.LookupData(source, 'id', variable_list) 19 | ).properties( 20 | width=500, 21 | height=300 22 | ).project( 23 | type='albersUsa' 24 | ).repeat( 25 | row=variable_list 26 | ).resolve_scale( 27 | color='independent' 28 | ) 29 | -------------------------------------------------------------------------------- /altair/examples/weather_heatmap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Seattle Weather Heatmap 3 | ----------------------- 4 | This example shows the 2010 daily high temperature (F) in Seattle, WA. 5 | """ 6 | # category: case studies 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | # Since the data is more than 5,000 rows we'll import it from a URL 11 | source = data.seattle_temps.url 12 | 13 | alt.Chart( 14 | source, 15 | title="2010 Daily High Temperature (F) in Seattle, WA" 16 | ).mark_rect().encode( 17 | x=alt.X('date:O', timeUnit='date'), 18 | y=alt.Y('date:O', timeUnit='month'), 19 | color=alt.Color('temp:Q', aggregate='max'), 20 | tooltip=[ 21 | alt.Tooltip('date:T', timeUnit='monthdate', title='Date'), 22 | alt.Tooltip('temp:Q', aggregate='max', title='Max Temp') 23 | ] 24 | ).properties(width=600) 25 | -------------------------------------------------------------------------------- /altair/examples/layered_chart_bar_mark.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar and Tick Chart 3 | ------------------ 4 | How to layer a tick chart on top of a bar chart. 5 | """ 6 | # category: bar charts 7 | import altair as alt 8 | import pandas as pd 9 | 10 | source = pd.DataFrame({ 11 | 'project': ['a', 'b', 'c', 'd', 'e', 'f', 'g'], 12 | 'score': [25, 57, 23, 19, 8, 47, 8], 13 | 'goal': [25, 47, 30, 27, 38, 19, 4] 14 | }) 15 | 16 | base = alt.Chart(source) 17 | 18 | bar = base.mark_bar().encode( 19 | x='project', 20 | y='score' 21 | ) 22 | 23 | tick = base.mark_tick( 24 | color='red', 25 | thickness=2 26 | ).encode( 27 | x='project', 28 | y='goal' 29 | ) 30 | 31 | (bar + tick).configure_tick( 32 | bandSize=35 # controls the width of the tick 33 | ).configure_scale( 34 | rangeStep=40 # controls the width of the bar 35 | ) 36 | -------------------------------------------------------------------------------- /altair/examples/bar_chart_with_highlighted_segment.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bar Chart with Highlighted Segment 3 | ---------------------------------- 4 | This example shows a bar chart that highlights values beyond a threshold. 5 | """ 6 | import altair as alt 7 | import pandas as pd 8 | from vega_datasets import data 9 | 10 | source = data.wheat() 11 | threshold = pd.DataFrame([{"threshold": 90}]) 12 | 13 | bars = alt.Chart(source).mark_bar().encode( 14 | x="year:O", 15 | y="wheat:Q", 16 | ) 17 | 18 | highlight = alt.Chart(source).mark_bar(color="#e45755").encode( 19 | x='year:O', 20 | y='baseline:Q', 21 | y2='wheat:Q' 22 | ).transform_filter( 23 | alt.datum.wheat > 90 24 | ).transform_calculate("baseline", "90") 25 | 26 | rule = alt.Chart(threshold).mark_rule().encode( 27 | y='threshold:Q' 28 | ) 29 | 30 | (bars + highlight + rule).properties(width=600) 31 | -------------------------------------------------------------------------------- /altair/examples/airports.py: -------------------------------------------------------------------------------- 1 | """ 2 | Locations of US Airports 3 | ======================== 4 | This is a layered geographic visualization that shows the positions of US 5 | airports on a background of US states. 6 | """ 7 | # category: case studies 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | airports = data.airports() 12 | states = alt.topo_feature(data.us_10m.url, feature='states') 13 | 14 | # US states background 15 | background = alt.Chart(states).mark_geoshape( 16 | fill='lightgray', 17 | stroke='white' 18 | ).properties( 19 | width=500, 20 | height=300 21 | ).project('albersUsa') 22 | 23 | # airport positions on background 24 | points = alt.Chart(airports).mark_circle().encode( 25 | longitude='longitude:Q', 26 | latitude='latitude:Q', 27 | size=alt.value(10), 28 | color=alt.value('steelblue') 29 | ) 30 | 31 | background + points 32 | -------------------------------------------------------------------------------- /altair/examples/world_projections.py: -------------------------------------------------------------------------------- 1 | """ 2 | World Projections 3 | ----------------- 4 | This example shows a map of the countries of the world using four available 5 | geographic projections. For more details on the projections available in 6 | Altair, see https://vega.github.io/vega-lite/docs/projection.html 7 | """ 8 | # category: maps 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = alt.topo_feature(data.world_110m.url, 'countries') 13 | 14 | base = alt.Chart(source).mark_geoshape( 15 | fill='#666666', 16 | stroke='white' 17 | ).properties( 18 | width=300, 19 | height=180 20 | ) 21 | 22 | projections = ['equirectangular', 'mercator', 'orthographic', 'gnomonic'] 23 | charts = [base.project(proj).properties(title=proj) 24 | for proj in projections] 25 | 26 | alt.vconcat( 27 | alt.hconcat(*charts[:2]), 28 | alt.hconcat(*charts[2:]) 29 | ) 30 | -------------------------------------------------------------------------------- /altair/examples/selection_histogram.py: -------------------------------------------------------------------------------- 1 | """ 2 | Selection Histogram 3 | =================== 4 | This chart shows an example of using an interval selection to filter the 5 | contents of an attached histogram, allowing the user to see the proportion 6 | of items in each category within the selection. 7 | """ 8 | # category: interactive charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.cars() 13 | 14 | brush = alt.selection(type='interval') 15 | 16 | points = alt.Chart().mark_point().encode( 17 | x='Horsepower:Q', 18 | y='Miles_per_Gallon:Q', 19 | color=alt.condition(brush, 'Origin:N', alt.value('lightgray')) 20 | ).add_selection( 21 | brush 22 | ) 23 | 24 | bars = alt.Chart().mark_bar().encode( 25 | y='Origin:N', 26 | color='Origin:N', 27 | x='count(Origin):Q' 28 | ).transform_filter( 29 | brush 30 | ) 31 | 32 | alt.vconcat(points, bars, data=source) 33 | -------------------------------------------------------------------------------- /altair/examples/error_bars_with_ci.py: -------------------------------------------------------------------------------- 1 | """ 2 | Error Bars showing Confidence Interval 3 | ====================================== 4 | This example shows how to show error bars using confidence intervals. The confidence intervals are computed internally in vega by a non-parametric `bootstrap of the mean `_. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | base = alt.Chart(source) 13 | 14 | points = base.mark_point(filled=True).encode( 15 | alt.X( 16 | 'mean(yield)', 17 | title='Barley Yield', 18 | scale=alt.Scale(zero=False), 19 | ), 20 | y='variety', 21 | color=alt.value('black') 22 | ) 23 | 24 | error_bars = base.mark_rule().encode( 25 | x='ci0(yield)', 26 | x2='ci1(yield)', 27 | y='variety' 28 | ) 29 | 30 | points + error_bars 31 | -------------------------------------------------------------------------------- /altair/examples/layered_heatmap_text.py: -------------------------------------------------------------------------------- 1 | """ 2 | Text over a Heatmap 3 | ------------------- 4 | 5 | An example of a layered chart of text over a heatmap using the cars dataset. 6 | """ 7 | # category: other charts 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.cars() 12 | 13 | # Configure common options 14 | base = alt.Chart(source) 15 | scale = alt.Scale(paddingInner=0) 16 | 17 | # Configure heatmap 18 | heatmap = base.mark_rect().encode( 19 | alt.X('Cylinders:O', scale=scale), 20 | alt.Y('Origin:O', scale=scale), 21 | color='count()' 22 | ) 23 | 24 | # Configure text 25 | text = base.mark_text(baseline='middle').encode( 26 | x='Cylinders:O', 27 | y='Origin:O', 28 | text='count()', 29 | color=alt.condition( 30 | alt.datum['count_*'] > 100, 31 | alt.value('black'), 32 | alt.value('white') 33 | ) 34 | ) 35 | 36 | # Draw the chart 37 | heatmap + text 38 | -------------------------------------------------------------------------------- /altair/examples/parallel_coordinates.py: -------------------------------------------------------------------------------- 1 | """ 2 | Parallel Coordinates Example 3 | ---------------------------- 4 | A `Parallel Coordinates `_ 5 | chart is a chart that lets you visualize the individual data points by drawing 6 | a single line for each of them. 7 | Such a chart can be created in Altair, but requires some data preprocessing 8 | to transform the data into a suitable representation. 9 | This example shows a parallel coordinates chart with the Iris dataset. 10 | """ 11 | # category: other charts 12 | 13 | import altair as alt 14 | from vega_datasets import data 15 | 16 | source = data.iris() 17 | source_transformed = source.reset_index().melt(['species', 'index']) 18 | 19 | alt.Chart(source_transformed).mark_line().encode( 20 | x='variable:N', 21 | y='value:Q', 22 | color='species:N', 23 | detail='index:N', 24 | opacity=alt.value(0.5) 25 | ).properties(width=500) 26 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Feedback and Contribution 2 | 3 | We welcome any input, feedback, bug reports, and contributions via [Altair's 4 | GitHub Repository](http://github.com/altair-viz/altair/). In particular, we 5 | welcome companion efforts from other visualization libraries to render the 6 | Vega-Lite specifications output by Altair. We see this portion of the effort 7 | as much bigger than Altair itself: the Vega and Vega-Lite specifications are 8 | perhaps the best existing candidates for a principled *lingua franca* of data 9 | visualization. 10 | 11 | We are also seeking contributions of additional Jupyter notebook-based examples 12 | in our separate GitHub repository: https://github.com/altair-viz/altair_notebooks. 13 | 14 | The altair users mailing list can be found at https://groups.google.com/forum/#!forum/altair-viz. If you are working on Altair, you can talk to other developers in the `#altair` channel of the [Vega slack](https://bit.ly/join-vega-slack). 15 | -------------------------------------------------------------------------------- /altair/expr/consts.py: -------------------------------------------------------------------------------- 1 | from .core import ConstExpression 2 | 3 | 4 | CONST_LISTING = { 5 | "NaN": "not a number (same as JavaScript literal NaN)", 6 | "LN10": "the natural log of 10 (alias to Math.LN10)", 7 | "E": "the transcendental number e (alias to Math.E)", 8 | "LOG10E": "the base 10 logarithm e (alias to Math.LOG10E)", 9 | "LOG2E": "the base 2 logarithm of e (alias to Math.LOG2E)", 10 | "SQRT1_2": "the square root of 0.5 (alias to Math.SQRT1_2)", 11 | "LN2": "the natural log of 2 (alias to Math.LN2)", 12 | "SQRT2": "the square root of 2 (alias to Math.SQRT1_2)", 13 | "PI": "the transcendental number pi (alias to Math.PI)" 14 | } 15 | 16 | NAME_MAP = {} 17 | 18 | 19 | def _populate_namespace(): 20 | globals_ = globals() 21 | for name, doc in CONST_LISTING.items(): 22 | py_name = NAME_MAP.get(name, name) 23 | globals_[py_name] = ConstExpression(name, doc) 24 | yield py_name 25 | 26 | 27 | __all__ = list(_populate_namespace()) 28 | -------------------------------------------------------------------------------- /altair/examples/selection_layer_bar_month.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interactive Average 3 | =================== 4 | The plot below uses an interval selection, which causes the chart to include an interactive brush 5 | (shown in grey). The brush selection parameterizes the red guideline, which visualizes the average 6 | value within the selected interval. 7 | """ 8 | # category: interactive charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.seattle_weather() 13 | brush = alt.selection(type='interval', encodings=['x']) 14 | 15 | bars = alt.Chart().mark_bar().encode( 16 | x='month(date):O', 17 | y='mean(precipitation):Q', 18 | opacity=alt.condition(brush, alt.OpacityValue(1), alt.OpacityValue(0.7)) 19 | ).add_selection( 20 | brush 21 | ) 22 | 23 | line = alt.Chart().mark_rule(color='firebrick').encode( 24 | y='mean(precipitation):Q', 25 | size=alt.SizeValue(3) 26 | ).transform_filter( 27 | brush 28 | ) 29 | 30 | alt.layer(bars, line, data=source) 31 | -------------------------------------------------------------------------------- /altair/examples/top_k_items.py: -------------------------------------------------------------------------------- 1 | """ 2 | Top K Items 3 | ----------- 4 | This example shows how to use the window and transformation filter to display 5 | the Top items of a long list of items in decreasing order. 6 | The sorting of the x-axis is needed for vega-lite and for the example does 7 | not do anything since we already have a unique value. 8 | Here we sort the top 10 highest ranking movies of IMDB. 9 | """ 10 | # category: case studies 11 | import altair as alt 12 | from vega_datasets import data 13 | 14 | source = data.movies.url 15 | 16 | # Top 10 movies by IMBD rating 17 | alt.Chart( 18 | source, 19 | ).mark_bar().encode( 20 | x=alt.X( 21 | 'Title:N', 22 | sort=alt.EncodingSortField(field="IMDB_Rating", op="mean", order='descending') 23 | ), 24 | y=alt.Y('IMDB_Rating:Q'), 25 | color=alt.Color('IMDB_Rating:Q') 26 | 27 | ).transform_window( 28 | rank='rank(IMDB_Rating)', 29 | sort=[alt.SortField('IMDB_Rating', order='descending')] 30 | ).transform_filter( 31 | (alt.datum.rank < 10) 32 | ) -------------------------------------------------------------------------------- /altair/examples/layered_histogram.py: -------------------------------------------------------------------------------- 1 | """ 2 | Layered Histogram 3 | ================= 4 | This example shows how to use opacity to make a layered histogram in Altair. 5 | """ 6 | # category: histograms 7 | import pandas as pd 8 | import altair as alt 9 | import numpy as np 10 | np.random.seed(42) 11 | 12 | # Generating Data 13 | source = pd.DataFrame({'Trial A': np.random.normal(0, 0.8, 1000), 14 | 'Trial B': np.random.normal(-2, 1, 1000), 15 | 'Trial C': np.random.normal(3, 2, 1000)}) 16 | 17 | # Tidying Data 18 | source = pd.melt( 19 | source, 20 | id_vars=source.index.name, 21 | value_vars=source.columns, 22 | var_name='Experiment', 23 | value_name='Measurement' 24 | ) 25 | 26 | alt.Chart(source).mark_area( 27 | opacity=0.3, 28 | interpolate='step' 29 | ).encode( 30 | alt.X('Measurement', bin=alt.Bin(maxbins=100)), 31 | alt.Y('count()', stack=None), 32 | alt.Color( 33 | 'Experiment', 34 | scale=alt.Scale(range=['#0000ff', '#008000', '#ff0000']) 35 | ) 36 | ) 37 | -------------------------------------------------------------------------------- /altair/examples/multiline_highlight.py: -------------------------------------------------------------------------------- 1 | """ 2 | Multi-Line Highlight 3 | ==================== 4 | This multi-line chart uses an invisible Voronoi tessellation to handle mouseover to 5 | identify the nearest point and then highlight the line on which the point falls. 6 | It is adapted from the Vega-Lite example found at 7 | https://bl.ocks.org/amitkaps/fe4238e716db53930b2f1a70d3401701 8 | """ 9 | # category: interactive charts 10 | import altair as alt 11 | from vega_datasets import data 12 | 13 | source = data.stocks() 14 | 15 | highlight = alt.selection(type='single', on='mouseover', 16 | fields=['symbol'], nearest=True) 17 | 18 | base = alt.Chart(source).encode( 19 | x='date:T', 20 | y='price:Q', 21 | color='symbol:N' 22 | ) 23 | 24 | points = base.mark_circle().encode( 25 | opacity=alt.value(0) 26 | ).add_selection( 27 | highlight 28 | ).properties( 29 | width=600 30 | ) 31 | 32 | lines = base.mark_line().encode( 33 | size=alt.condition(~highlight, alt.value(1), alt.value(3)) 34 | ) 35 | 36 | points + lines 37 | -------------------------------------------------------------------------------- /altair/vegalite/v1/data.py: -------------------------------------------------------------------------------- 1 | from ..data import (MaxRowsError, curry, default_data_transformer, limit_rows, 2 | pipe, sample, to_csv, to_json, to_values, DataTransformerRegistry) 3 | 4 | 5 | # ============================================================================== 6 | # VegaLite 1 data transformers 7 | # ============================================================================== 8 | 9 | 10 | ENTRY_POINT_GROUP = 'altair.vegalite.v1.data_transformer' # type: str 11 | 12 | 13 | data_transformers = DataTransformerRegistry(entry_point_group=ENTRY_POINT_GROUP) # type: DataTransformerRegistry 14 | data_transformers.register('default', default_data_transformer) 15 | data_transformers.register('json', to_json) 16 | data_transformers.register('csv', to_csv) 17 | data_transformers.enable('default') 18 | 19 | 20 | __all__ = ( 21 | 'MaxRowsError', 22 | 'curry', 23 | 'default_data_transformer', 24 | 'limit_rows', 25 | 'pipe', 26 | 'sample', 27 | 'to_csv', 28 | 'to_json', 29 | 'to_values', 30 | 'data_transformers' 31 | ) 32 | -------------------------------------------------------------------------------- /altair/vegalite/v2/data.py: -------------------------------------------------------------------------------- 1 | from ..data import (MaxRowsError, curry, default_data_transformer, limit_rows, 2 | pipe, sample, to_csv, to_json, to_values, DataTransformerRegistry) 3 | 4 | 5 | # ============================================================================== 6 | # VegaLite 1 data transformers 7 | # ============================================================================== 8 | 9 | 10 | ENTRY_POINT_GROUP = 'altair.vegalite.v2.data_transformer' # type: str 11 | 12 | 13 | data_transformers = DataTransformerRegistry(entry_point_group=ENTRY_POINT_GROUP) # type: DataTransformerRegistry 14 | data_transformers.register('default', default_data_transformer) 15 | data_transformers.register('json', to_json) 16 | data_transformers.register('csv', to_csv) 17 | data_transformers.enable('default') 18 | 19 | 20 | __all__ = ( 21 | 'MaxRowsError', 22 | 'curry', 23 | 'default_data_transformer', 24 | 'limit_rows', 25 | 'pipe', 26 | 'sample', 27 | 'to_csv', 28 | 'to_json', 29 | 'to_values', 30 | 'data_transformers' 31 | ) 32 | -------------------------------------------------------------------------------- /altair/vega/data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from toolz.curried import curry, pipe 3 | from ..utils.core import sanitize_dataframe 4 | from ..utils.data import ( 5 | MaxRowsError, sample, to_csv, to_json, to_values, check_data_type 6 | ) 7 | 8 | 9 | @curry 10 | def limit_rows(data, max_rows=5000): 11 | """Raise MaxRowsError if the data model has more than max_rows.""" 12 | if not isinstance(data, (list, pd.DataFrame)): 13 | raise TypeError('Expected dict or DataFrame, got: {}'.format(type(data))) 14 | if len(data) > max_rows: 15 | raise MaxRowsError('The number of rows in your dataset is greater than the max of {}'.format(max_rows)) 16 | return data 17 | 18 | 19 | @curry 20 | def default_data_transformer(data): 21 | return pipe(data, limit_rows, to_values) 22 | 23 | 24 | __all__ = ( 25 | 'MaxRowsError', 26 | 'curry', 27 | 'default_data_transformer', 28 | 'limit_rows', 29 | 'pipe', 30 | 'sanitize_dataframe', 31 | 'sample', 32 | 'to_csv', 33 | 'to_json', 34 | 'to_values', 35 | 'check_data_type' 36 | ) 37 | -------------------------------------------------------------------------------- /altair/examples/isotype_grid.py: -------------------------------------------------------------------------------- 1 | """ 2 | Isotype Grid 3 | ------------ 4 | This example is a grid of isotype figures. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | import pandas as pd 9 | 10 | data = pd.DataFrame([dict(id=i) for i in range(1, 101)]) 11 | 12 | person = ( 13 | "M1.7 -1.7h-0.8c0.3 -0.2 0.6 -0.5 0.6 -0.9c0 -0.6 " 14 | "-0.4 -1 -1 -1c-0.6 0 -1 0.4 -1 1c0 0.4 0.2 0.7 0.6 " 15 | "0.9h-0.8c-0.4 0 -0.7 0.3 -0.7 0.6v1.9c0 0.3 0.3 0.6 " 16 | "0.6 0.6h0.2c0 0 0 0.1 0 0.1v1.9c0 0.3 0.2 0.6 0.3 " 17 | "0.6h1.3c0.2 0 0.3 -0.3 0.3 -0.6v-1.8c0 0 0 -0.1 0 " 18 | "-0.1h0.2c0.3 0 0.6 -0.3 0.6 -0.6v-2c0.2 -0.3 -0.1 " 19 | "-0.6 -0.4 -0.6z" 20 | ) 21 | 22 | alt.Chart(data).transform_calculate( 23 | row="ceil(datum.id/10)" 24 | ).transform_calculate( 25 | col="datum.id - datum.row*10" 26 | ).mark_point( 27 | filled=True, 28 | size=50 29 | ).encode( 30 | x=alt.X("col:O", axis=None), 31 | y=alt.Y("row:O", axis=None), 32 | shape=alt.ShapeValue(person) 33 | ).properties( 34 | width=400, 35 | height=400 36 | ).configure_view( 37 | strokeWidth=0 38 | ) 39 | -------------------------------------------------------------------------------- /tools/schemapi/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from ..utils import get_valid_identifier 4 | from ..schemapi import _FromDict 5 | 6 | 7 | @pytest.fixture 8 | def refschema(): 9 | return { 10 | '$ref': '#/definitions/Foo', 11 | 'definitions': { 12 | 'Foo': {'$ref': '#/definitions/Bar'}, 13 | 'Bar': {'$ref': '#/definitions/Baz'}, 14 | 'Baz': {'type': 'string'} 15 | } 16 | } 17 | 18 | 19 | def test_get_valid_identifier(): 20 | assert get_valid_identifier('$schema') == 'schema' 21 | assert get_valid_identifier('$ref') == 'ref' 22 | assert get_valid_identifier('foo-bar') == 'foobar' 23 | assert get_valid_identifier('$as') == 'as_' 24 | assert get_valid_identifier('for') == 'for_' 25 | assert get_valid_identifier('--') == '_' 26 | 27 | 28 | @pytest.mark.parametrize('use_json', [True, False]) 29 | def test_hash_schema(refschema, use_json): 30 | copy = refschema.copy() 31 | copy['description'] = "A schema" 32 | copy['title'] = "Schema to test" 33 | assert _FromDict.hash_schema(refschema) == _FromDict.hash_schema(copy) 34 | -------------------------------------------------------------------------------- /altair/examples/us_population_over_time.py: -------------------------------------------------------------------------------- 1 | """ 2 | US Population Over Time 3 | ======================= 4 | This chart visualizes the age distribution of the US population over time. 5 | It uses a slider widget that is bound to the year to visualize the age 6 | distribution over time. 7 | """ 8 | # category: case studies 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.population.url 13 | 14 | pink_blue = alt.Scale(domain=('Male', 'Female'), 15 | range=["steelblue", "salmon"]) 16 | 17 | slider = alt.binding_range(min=1900, max=2000, step=10) 18 | select_year = alt.selection_single(name="year", fields=['year'], bind=slider) 19 | 20 | alt.Chart(source).mark_bar().encode( 21 | x=alt.X('sex:N', title=None), 22 | y=alt.Y('people:Q', scale=alt.Scale(domain=(0, 12000000))), 23 | color=alt.Color('sex:N', scale=pink_blue), 24 | column='age:O' 25 | ).properties( 26 | width=20 27 | ).add_selection( 28 | select_year 29 | ).transform_calculate( 30 | "sex", alt.expr.if_(alt.datum.sex == 1, "Male", "Female") 31 | ).transform_filter( 32 | select_year 33 | ) 34 | -------------------------------------------------------------------------------- /altair/examples/stem_and_leaf.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stem and Leaf Plot 3 | ------------------ 4 | This example shows how to make a stem and leaf plot. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | import pandas as pd 9 | import numpy as np 10 | np.random.seed(42) 11 | 12 | # Generating random data 13 | source = pd.DataFrame({'samples': np.random.normal(50, 15, 100).astype(int).astype(str)}) 14 | 15 | # Splitting stem and leaf 16 | source['stem'] = source['samples'].str[:-1] 17 | source['leaf'] = source['samples'].str[-1] 18 | 19 | source = source.sort_values(by=['stem', 'leaf']) 20 | 21 | # Determining leaf position 22 | source['position'] = source.groupby('stem').cumcount().add(1) 23 | 24 | # Creating stem and leaf plot 25 | alt.Chart(source).mark_text( 26 | align='left', 27 | baseline='middle', 28 | dx=-5 29 | ).encode( 30 | alt.X('position:Q', title='', 31 | axis=alt.Axis(ticks=False, labels=False, grid=False) 32 | ), 33 | alt.Y('stem:N', title='', axis=alt.Axis(tickSize=0)), 34 | text='leaf:N' 35 | ).configure_axis( 36 | labelFontSize=20 37 | ).configure_text( 38 | fontSize=20 39 | ) 40 | -------------------------------------------------------------------------------- /altair/examples/axes_scales.py: -------------------------------------------------------------------------------- 1 | """ 2 | Controlling Axis Scale 3 | ---------------------- 4 | A few examples that make use of alternate Y axis scales. 5 | """ 6 | # category: other charts 7 | 8 | import altair as alt 9 | import numpy as np 10 | import pandas as pd 11 | 12 | chart_df = pd.DataFrame( 13 | { 14 | 'x': list(range(0,20)), 15 | 'y': [2** x for x in range(0,20)], 16 | } 17 | ) 18 | 19 | base_chart = alt.Chart(chart_df).mark_line().encode( 20 | x=alt.X('x:Q'), 21 | ).properties( 22 | height=200, 23 | width=200, 24 | ) 25 | 26 | chart_linear = base_chart.encode( 27 | y=alt.Y('y:Q'), 28 | ).properties(title='linear') 29 | 30 | chart_base_2 = base_chart.encode( 31 | y=alt.Y('y:Q', scale=alt.Scale(type='log', base=2)), 32 | ).properties(title='log base 2') 33 | 34 | chart_base_e = base_chart.encode( 35 | y=alt.Y('y:Q', scale=alt.Scale(type='log', base=np.e)), 36 | ).properties(title='log base e') 37 | 38 | chart_base_10 = base_chart.encode( 39 | y=alt.Y('y:Q', scale=alt.Scale(type='log')), 40 | ).properties(title='log base 10') 41 | 42 | (chart_linear | chart_base_2) & (chart_base_e | chart_base_10) 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | # emacs backups 60 | *~ 61 | \#*\# 62 | 63 | .ipynb_checkpoints 64 | .idea/* 65 | tools/_build 66 | Untitled*.ipynb 67 | .mypy* 68 | .pytest_cache 69 | *.DS_Store 70 | 71 | # VSCode 72 | .vscode -------------------------------------------------------------------------------- /altair/examples/boxplot_max_min.py: -------------------------------------------------------------------------------- 1 | """ 2 | Box Plot with Min/Max Whiskers 3 | ------------------------------ 4 | This example shows how to make a basic box plot using US Population data from 2000. 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.population.url 11 | 12 | base = alt.Chart(source) 13 | 14 | # Define aggregate fields 15 | lower_box = 'q1(people):Q' 16 | lower_whisker = 'min(people):Q' 17 | upper_box = 'q3(people):Q' 18 | upper_whisker = 'max(people):Q' 19 | 20 | # Compose each layer individually 21 | lower_plot = base.mark_rule().encode( 22 | y=alt.Y(lower_whisker, title="population"), 23 | y2=lower_box, 24 | x='age:O' 25 | ) 26 | 27 | middle_plot = base.mark_bar(size=5.0).encode( 28 | y=lower_box, 29 | y2=upper_box, 30 | x='age:O' 31 | ) 32 | 33 | upper_plot = base.mark_rule().encode( 34 | y=upper_whisker, 35 | y2=upper_box, 36 | x='age:O' 37 | ) 38 | 39 | middle_tick = base.mark_tick( 40 | color='white', 41 | size=5.0 42 | ).encode( 43 | y='median(people):Q', 44 | x='age:O', 45 | ) 46 | 47 | lower_plot + middle_plot + upper_plot + middle_tick 48 | -------------------------------------------------------------------------------- /doc/_static/chart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /altair/examples/ranged_dot_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ranged Dot Plot 3 | ----------------- 4 | This example shows a ranged dot plot that uses 'layer' to convey changing life expectancy for the five most populous countries (between 1955 and 2000). 5 | """ 6 | # category: other charts 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.countries.url 11 | 12 | chart = alt.layer( 13 | data=source 14 | ).transform_filter( 15 | filter={"field": 'country', 16 | "oneOf": ["China", "India", "United States", "Indonesia", "Brazil"]} 17 | ).transform_filter( 18 | filter={'field': 'year', 19 | "oneOf": [1955, 2000]} 20 | ) 21 | 22 | chart += alt.Chart().mark_line(color='#db646f').encode( 23 | x='life_expect:Q', 24 | y='country:N', 25 | detail='country:N' 26 | ) 27 | # Add points for life expectancy in 1955 & 2000 28 | chart += alt.Chart().mark_point( 29 | size=100, 30 | opacity=1, 31 | filled=True 32 | ).encode( 33 | x='life_expect:Q', 34 | y='country:N', 35 | color=alt.Color('year:O', 36 | scale=alt.Scale( 37 | domain=['1955', '2000'], 38 | range=['#e6959c', '#911a24'] 39 | ) 40 | ) 41 | ).interactive() 42 | 43 | chart 44 | -------------------------------------------------------------------------------- /altair/examples/simple_scatter_with_errorbars.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple Scatter Plot with Errorbars 3 | ---------------------------------- 4 | 5 | A simple scatter plot of a data set with errorbars. 6 | 7 | """ 8 | # category: scatter plots 9 | import altair as alt 10 | import pandas as pd 11 | import numpy as np 12 | 13 | # generate some data points with uncertainties 14 | np.random.seed(0) 15 | x = [1, 2, 3, 4, 5] 16 | y = np.random.normal(10, 0.5, size=len(x)) 17 | yerr = 0.2 18 | 19 | # set up data frame 20 | source = pd.DataFrame({"x":x, "y":y, "yerr":yerr}) 21 | 22 | # the base chart 23 | base = alt.Chart(source) 24 | 25 | # generate the points 26 | points = base.mark_point(filled=True, size=50).encode( 27 | x=alt.X( 28 | 'x', 29 | title='x', 30 | scale=alt.Scale(domain=(0,6)) 31 | ), 32 | y=alt.Y( 33 | 'y', 34 | title='y', 35 | scale=alt.Scale(zero=False, domain=(10, 11)) 36 | ), 37 | color=alt.value('black') 38 | ) 39 | 40 | # generate the error bars 41 | errorbars = base.mark_rule().encode( 42 | x="x", 43 | y="ymin:Q", 44 | y2="ymax:Q" 45 | ).transform_calculate( 46 | ymin="datum.y-datum.yerr", 47 | ymax="datum.y+datum.yerr" 48 | ) 49 | 50 | points + errorbars 51 | -------------------------------------------------------------------------------- /design/altair-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | Altair Logo 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /doc/getting_started/overview.rst: -------------------------------------------------------------------------------- 1 | .. _overview: 2 | 3 | Overview 4 | ======== 5 | 6 | Altair is a declarative statistical visualization library for Python, based on 7 | Vega_ and Vega-Lite_. 8 | 9 | Altair offers a powerful and concise visualization grammar that enables you to build 10 | a wide range of statistical visualizations quickly. Here is an example of using the 11 | Altair API to quickly visualize a dataset with 12 | an interactive scatter plot: 13 | 14 | .. altair-plot:: 15 | 16 | import altair as alt 17 | 18 | # load a simple dataset as a pandas DataFrame 19 | from vega_datasets import data 20 | cars = data.cars() 21 | 22 | alt.Chart(cars).mark_point().encode( 23 | x='Horsepower', 24 | y='Miles_per_Gallon', 25 | color='Origin', 26 | ).interactive() 27 | 28 | The key idea is that you are declaring links between *data columns* and *visual encoding 29 | channels*, such as the x-axis, y-axis, color, etc. The rest of the plot details are 30 | handled automatically. Building on this declarative plotting idea, a surprising range 31 | of simple to sophisticated plots and visualizations can be created using a relatively 32 | concise grammar. 33 | 34 | .. _Vega: http://vega.github.io/vega 35 | .. _Vega-Lite: http://vega.github.io/vega-lite 36 | -------------------------------------------------------------------------------- /design/altair-logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | Altair Logo Light 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /altair/examples/us_state_capitals.py: -------------------------------------------------------------------------------- 1 | """ 2 | U.S. state capitals overlayed on a map of the U.S 3 | ------------------------------------------------- 4 | This is a layered geographic visualization that shows US capitals 5 | overlayed on a map. 6 | """ 7 | # category: case studies 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | states = alt.topo_feature(data.us_10m.url, 'states') 12 | capitals = data.us_state_capitals.url 13 | 14 | # US states background 15 | background = alt.Chart(states).mark_geoshape( 16 | fill='lightgray', 17 | stroke='white' 18 | ).properties( 19 | title='US State Capitols', 20 | width=700, 21 | height=400 22 | ).project('albersUsa') 23 | 24 | # Points and text 25 | hover = alt.selection(type='single', on='mouseover', nearest=True, 26 | fields=['lat', 'lon']) 27 | 28 | base = alt.Chart(capitals).encode( 29 | longitude='lon:Q', 30 | latitude='lat:Q' 31 | ) 32 | 33 | text = base.mark_text(dy=-5, align='right').encode( 34 | alt.Text('city', type='nominal'), 35 | opacity=alt.condition(~hover, alt.value(0), alt.value(1)) 36 | ) 37 | 38 | points = base.mark_point().encode( 39 | color=alt.value('black'), 40 | size=alt.condition(~hover, alt.value(30), alt.value(100)) 41 | ).add_selection(hover) 42 | 43 | background + points + text 44 | -------------------------------------------------------------------------------- /altair/examples/horizon_graph.py: -------------------------------------------------------------------------------- 1 | """ 2 | Horizon Graph 3 | ------------- 4 | This example shows how to make a Horizon Graph with 2 layers. (See https://idl.cs.washington.edu/papers/horizon/ for more details on Horizon Graphs.) 5 | """ 6 | # category: area charts 7 | import altair as alt 8 | import pandas as pd 9 | 10 | source = pd.DataFrame([ 11 | {"x": 1, "y": 28}, {"x": 2, "y": 55}, 12 | {"x": 3, "y": 43}, {"x": 4, "y": 91}, 13 | {"x": 5, "y": 81}, {"x": 6, "y": 53}, 14 | {"x": 7, "y": 19}, {"x": 8, "y": 87}, 15 | {"x": 9, "y": 52}, {"x": 10, "y": 48}, 16 | {"x": 11, "y": 24}, {"x": 12, "y": 49}, 17 | {"x": 13, "y": 87}, {"x": 14, "y": 66}, 18 | {"x": 15, "y": 17}, {"x": 16, "y": 27}, 19 | {"x": 17, "y": 68}, {"x": 18, "y": 16}, 20 | {"x": 19, "y": 49}, {"x": 20, "y": 15} 21 | ]) 22 | 23 | area1 = alt.Chart(source).mark_area( 24 | clip=True, 25 | interpolate='monotone' 26 | ).encode( 27 | alt.X('x', scale=alt.Scale(zero=False, nice=False)), 28 | alt.Y('y', scale=alt.Scale(domain=[0, 50]), title='y'), 29 | opacity=alt.value(0.6) 30 | ).properties( 31 | width=500, 32 | height=75 33 | ) 34 | 35 | area2 = area1.encode( 36 | alt.Y('ny:Q', scale=alt.Scale(domain=[0, 50])) 37 | ).transform_calculate( 38 | "ny", alt.datum.y - 50 39 | ) 40 | 41 | area1 + area2 42 | -------------------------------------------------------------------------------- /doc/user_guide/importing.rst: -------------------------------------------------------------------------------- 1 | .. _importing: 2 | 3 | Importing Vega & Vega-Lite Versions 4 | =================================== 5 | 6 | The main Altair API is based on version 2.X of `Vega-Lite`_. The core of the API, 7 | found in the ``altair.vegalite.v2.schema`` module, is programmatically generated 8 | from the Vega-Lite schema. 9 | 10 | Altair additionally provides wrappers for several other schemas: 11 | 12 | - Vega-Lite 1.X in ``altair.vegalite.v1`` 13 | - Vega 2.X in ``altair.vega.v2`` 14 | - Vega 3.X in ``altair.vega.v3`` 15 | 16 | So, for example, if you would like to create Altair plots targeting Vega-Lite 17 | version 1, you can use:: 18 | 19 | import altair.vegalite.v1 as alt 20 | 21 | and then proceed to use the Altair version 1 API. 22 | 23 | .. note:: 24 | 25 | We strongly recommend all users transition to Vega-Lite 2.x and Vega 3.x. 26 | These versions support many new features, are more stable, and Altair 2.0 27 | works best with them. 28 | 29 | Because Altair has focused primarily on the vega-lite API, the vega wrappers are 30 | far less developed than the vega-lite wrappers, though it is possible to 31 | create Vega plots using a very low-level Python interface that mirrors the 32 | schema itself. 33 | 34 | 35 | .. _Vega-Lite: http://vega.github.io/vega-lite/ 36 | .. _Vega: http://vega.github.io/vega/ 37 | -------------------------------------------------------------------------------- /altair/examples/interactive_layered_crossfilter.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interactive Crossfilter 3 | ======================= 4 | This example shows a multi-panel view of the same data, where you can interactively 5 | select a portion of the data in any of the panels to highlight that portion in any 6 | of the other panels. 7 | """ 8 | # category: interactive charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = alt.UrlData( 13 | data.flights_2k.url, 14 | format={'parse': {'date': 'date'}} 15 | ) 16 | 17 | brush = alt.selection(type='interval', encodings=['x']) 18 | 19 | # Define the base chart, with the common parts of the 20 | # background and highlights 21 | base = alt.Chart().mark_bar().encode( 22 | x=alt.X(alt.repeat('column'), type='quantitative', bin=alt.Bin(maxbins=20)), 23 | y='count()' 24 | ).properties( 25 | width=180, 26 | height=130 27 | ) 28 | 29 | # blue background with selection 30 | background = base.properties(selection=brush) 31 | 32 | # yellow highlights on the transformed data 33 | highlight = base.encode( 34 | color=alt.value('goldenrod') 35 | ).transform_filter(brush) 36 | 37 | # layer the two charts & repeat 38 | alt.layer( 39 | background, 40 | highlight, 41 | data=source 42 | ).transform_calculate( 43 | "time", 44 | "hours(datum.date)" 45 | ).repeat(column=["distance", "delay", "time"]) 46 | -------------------------------------------------------------------------------- /altair/examples/beckers_barley_trellis_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Becker's Barley Trellis Plot 3 | ---------------------------- 4 | The example demonstrates the trellis charts created by Richard Becker, William Cleveland and others in the 1990s. Using the visualization technique below they identified an anomoly in a widely used agriculatural dataset, which they termed `"The Morris Mistake." `_. It became their favored way of showcasing the power of this pioneering plot. 5 | """ 6 | # category: case studies 7 | import altair as alt 8 | from vega_datasets import data 9 | 10 | source = data.barley() 11 | 12 | alt.Chart(source, title="The Morris Mistake").mark_point().encode( 13 | alt.X( 14 | 'yield:Q', 15 | title="Barley Yield (bushels/acre)", 16 | scale=alt.Scale(zero=False), 17 | axis=alt.Axis(grid=False) 18 | ), 19 | alt.Y( 20 | 'variety:N', 21 | title="", 22 | sort=alt.EncodingSortField(field='yield', op='sum', order='descending'), 23 | scale=alt.Scale(rangeStep=20), 24 | axis=alt.Axis(grid=True) 25 | ), 26 | color=alt.Color('year:N', legend=alt.Legend(title="Year")), 27 | row=alt.Row( 28 | 'site:N', 29 | title="", 30 | sort=alt.EncodingSortField(field='yield', op='sum', order='descending'), 31 | ) 32 | ).configure_view(stroke="transparent") 33 | -------------------------------------------------------------------------------- /altair/examples/dot_dash_plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dot Dash Plot 3 | ============= 4 | How to make the dot-dash plot presented in Edward Tufte's `Visual Display of Quantitative Information `_. Based 5 | on a JavaScript implementation by `g3o2 `_. 6 | """ 7 | # category: scatter plots 8 | import altair as alt 9 | from vega_datasets import data 10 | 11 | source = data.cars() 12 | 13 | # Configure the options common to all layers 14 | brush = alt.selection(type='interval') 15 | base = alt.Chart(source).add_selection(brush) 16 | 17 | # Configure the points 18 | points = base.mark_point().encode( 19 | x=alt.X('Miles_per_Gallon', title=''), 20 | y=alt.Y('Horsepower', title=''), 21 | color=alt.condition(brush, 'Origin', alt.value('grey')) 22 | ) 23 | 24 | # Configure the ticks 25 | tick_axis = alt.Axis(labels=False, domain=False, ticks=False) 26 | 27 | x_ticks = base.mark_tick().encode( 28 | alt.X('Miles_per_Gallon', axis=tick_axis), 29 | alt.Y('Origin', title='', axis=tick_axis), 30 | color=alt.condition(brush, 'Origin', alt.value('lightgrey')) 31 | ) 32 | 33 | y_ticks = base.mark_tick().encode( 34 | alt.X('Origin', title='', axis=tick_axis), 35 | alt.Y('Horsepower', axis=tick_axis), 36 | color=alt.condition(brush, 'Origin', alt.value('lightgrey')) 37 | ) 38 | 39 | # Build the chart 40 | y_ticks | (points & x_ticks) 41 | -------------------------------------------------------------------------------- /altair/examples/poly_fit.py: -------------------------------------------------------------------------------- 1 | """ 2 | Polynomial Fit Plot 3 | =================== 4 | This example shows how to overlay data with a fitted polynomial 5 | """ 6 | # category: scatter plots 7 | import numpy as np 8 | import pandas as pd 9 | import altair as alt 10 | 11 | # Generate some random data 12 | rng = np.random.RandomState(1) 13 | x = rng.rand(40) ** 2 14 | y = 10 - 1. / (x + 0.1) + rng.randn(40) 15 | df = pd.DataFrame({'x': x, 'y': y}) 16 | 17 | # Define the degree of the polynomial fit 18 | degree_list = [1, 3, 5] 19 | 20 | # Build a dataframe with the fitted data 21 | poly_data = pd.DataFrame({'xfit': np.linspace(df['x'].min(), df['x'].max(), 500)}) 22 | 23 | for degree in degree_list: 24 | poly_data[str(degree)] = np.poly1d(np.polyfit(df['x'], df['y'], degree))(poly_data['xfit']) 25 | 26 | # Tidy the dataframe so 'degree' is a variable 27 | poly_data = pd.melt(poly_data, 28 | id_vars=['xfit'], 29 | value_vars=[str(deg) for deg in degree_list], 30 | var_name='degree', value_name='yfit') 31 | 32 | # Plot the data points on an interactive axis 33 | points = alt.Chart(df).mark_circle(color='black').encode( 34 | x=alt.X('x', title='x'), 35 | y=alt.Y('y', title='y') 36 | ).interactive() 37 | 38 | # Plot the best fit polynomials 39 | polynomial_fit = alt.Chart(poly_data).mark_line().encode( 40 | x='xfit', 41 | y='yfit', 42 | color='degree' 43 | ) 44 | 45 | points + polynomial_fit 46 | -------------------------------------------------------------------------------- /altair/examples/interactive_cross_highlight.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interactive Chart with Cross-Highlight 3 | ====================================== 4 | This example shows an interactive chart where selections in one portion of 5 | the chart affect what is shown in other panels. Click on the bar chart to 6 | see a detail of the distribution in the upper panel. 7 | """ 8 | # category: interactive charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.movies.url 13 | 14 | pts = alt.selection(type="single", encodings=['x']) 15 | 16 | rect = alt.Chart(data.movies.url).mark_rect().encode( 17 | alt.X('IMDB_Rating:Q', bin=True), 18 | alt.Y('Rotten_Tomatoes_Rating:Q', bin=True), 19 | alt.Color('count()', 20 | scale=alt.Scale(scheme='greenblue'), 21 | legend=alt.Legend(title='Total Records') 22 | ) 23 | ) 24 | 25 | circ = rect.mark_point().encode( 26 | alt.ColorValue('grey'), 27 | alt.Size('count()', 28 | legend=alt.Legend(title='Records in Selection') 29 | ) 30 | ).transform_filter( 31 | pts 32 | ) 33 | 34 | bar = alt.Chart(source).mark_bar().encode( 35 | x='Major_Genre:N', 36 | y='count()', 37 | color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey")) 38 | ).properties( 39 | selection=pts, 40 | width=550, 41 | height=200 42 | ) 43 | 44 | alt.vconcat( 45 | rect + circ, 46 | bar 47 | ).resolve_legend( 48 | color="independent", 49 | size="independent" 50 | ) 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Brian E. Granger and Jake Vanderplas 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of altair nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /altair/examples/scatter_marginal_hist.py: -------------------------------------------------------------------------------- 1 | """ 2 | Facetted Scatterplot with marginal histograms 3 | --------------------------------------------- 4 | This example demonstrates how to generate a facetted scatterplot, 5 | with marginal facetted histograms, and how to share their respective 6 | - x,some y-limits. 7 | """ 8 | # category: other charts 9 | import altair as alt 10 | from vega_datasets import data 11 | 12 | source = data.iris() 13 | 14 | base = alt.Chart(source) 15 | 16 | xscale = alt.Scale(domain=(4.0, 8.0)) 17 | yscale = alt.Scale(domain=(1.9, 4.55)) 18 | 19 | area_args = {'opacity': .3, 'interpolate': 'step'} 20 | 21 | points = base.mark_circle().encode( 22 | alt.X('sepalLength', scale=xscale), 23 | alt.Y('sepalWidth', scale=yscale), 24 | color='species', 25 | ) 26 | 27 | top_hist = base.mark_area(**area_args).encode( 28 | alt.X('sepalLength:Q', 29 | # when using bins, the axis scale is set through 30 | # the bin extent, so we do not specify the scale here 31 | # (which would be ignored anyway) 32 | bin=alt.Bin(maxbins=20, extent=xscale.domain), 33 | stack=None, 34 | title='' 35 | ), 36 | alt.Y('count()', stack=None, title=''), 37 | alt.Color('species:N'), 38 | ).properties(height=60) 39 | 40 | right_hist = base.mark_area(**area_args).encode( 41 | alt.Y('sepalWidth:Q', 42 | bin=alt.Bin(maxbins=20, extent=yscale.domain), 43 | stack=None, 44 | title='', 45 | ), 46 | alt.X('count()', stack=None, title=''), 47 | alt.Color('species:N'), 48 | ).properties(width=60) 49 | 50 | top_hist & (points | right_hist) 51 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | 1. Update version to, e.g. 2.0.0 2 | 3 | - in altair/__init__.py 4 | - in doc/conf.py (two places) 5 | 6 | 2. Make sure CHANGES.md is up to date for the release 7 | 8 | 3. Commit change and push to master 9 | 10 | git add . -u 11 | git commit -m "MAINT: bump version to 2.0.0" 12 | git push origin master 13 | 14 | 4. Tag the release: 15 | 16 | git tag -a v2.0.0 -m "version 2.0.0 release" 17 | git push origin v2.0.0 18 | 19 | 5. Build source & wheel distributions 20 | 21 | rm -r dist build # clean old builds & distributions 22 | python setup.py sdist # create a source distribution 23 | python setup.py bdist_wheel # create a universal wheel 24 | 25 | 6. publish to PyPI (Requires correct PyPI owner permissions) 26 | 27 | twine upload dist/* 28 | 29 | 7. build and publish docs (Requires write-access to altair-viz/altair-viz.github.io) 30 | 31 | cd doc 32 | make clean 33 | make html 34 | bash sync_website.sh 35 | 36 | 8. update version to, e.g. 2.1.0dev 37 | 38 | - in altair/__init__.py 39 | - in doc/conf.py (two places) 40 | 41 | 9. add a new changelog entry for the unreleased version 42 | 43 | 10. Commit change and push to master 44 | 45 | git add . -u 46 | git commit -m "MAINT: bump version to 2.1.0dev" 47 | git push origin master 48 | 49 | 11. Update version and hash in the recipe at conda-forge/altair-feedstock: 50 | https://github.com/conda-forge/altair-feedstock/blob/master/recipe/meta.yaml 51 | & submit a pull request. 52 | 53 | Note: the conda-forge bot may take care of this automatically. 54 | -------------------------------------------------------------------------------- /altair/utils/tests/test_html.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from ..html import spec_to_html 4 | 5 | 6 | @pytest.fixture 7 | def spec(): 8 | return { 9 | 'data': {'url': 'data.json'}, 10 | 'mark': 'point', 11 | 'encoding': { 12 | 'x': {'field': 'x', 'type': 'quantitative'}, 13 | 'y': {'field': 'y', 'type': 'quantitative'} 14 | } 15 | } 16 | 17 | 18 | @pytest.mark.parametrize('requirejs', [True, False]) 19 | @pytest.mark.parametrize('fullhtml', [True, False]) 20 | def test_spec_to_html(requirejs, fullhtml, spec): 21 | # We can't test that the html actually renders, but we'll test aspects of 22 | # it to make certain that the keywords are respected. 23 | vegaembed_version="3.12", 24 | vegalite_version="3.0", 25 | vega_version="4.0" 26 | 27 | html = spec_to_html(spec, mode='vega-lite', 28 | requirejs=requirejs, fullhtml=fullhtml, 29 | vegalite_version=vegalite_version, 30 | vegaembed_version=vegaembed_version, 31 | vega_version=vega_version) 32 | html = html.strip() 33 | 34 | if fullhtml: 35 | assert html.startswith("") 36 | assert html.endswith("") 37 | else: 38 | assert html.startswith("