From 88c76e3f8ca320da4b6bde7b1d3f54389b75f1da Mon Sep 17 00:00:00 2001 From: Dan Redding <125183946+dangotbanned@users.noreply.github.com> Date: Sat, 2 Nov 2024 12:56:26 +0000 Subject: [PATCH] docs: Promote `when-then-otherwise` in User Guide (#3544) Co-authored-by: Dan Redding <125183946+dangotbanned@users.noreply.github.com> Co-authored-by: Joel Ostblom Co-authored-by: Joel Ostblom --- README.md | 2 +- altair/vegalite/v5/api.py | 29 ++- doc/case_studies/exploring-weather.rst | 31 ++- doc/user_guide/compound_charts.rst | 15 +- .../interactions/bindings_widgets.rst | 40 +--- doc/user_guide/interactions/expressions.rst | 13 +- doc/user_guide/interactions/jupyter_chart.rst | 20 +- doc/user_guide/interactions/parameters.rst | 226 +++++++++++++++--- doc/user_guide/marks/geoshape.rst | 11 +- doc/user_guide/marks/line.rst | 2 +- doc/user_guide/marks/text.rst | 7 +- doc/user_guide/times_and_dates.rst | 7 +- doc/user_guide/transform/filter.rst | 26 +- doc/user_guide/transform/pivot.rst | 24 +- .../bar_chart_with_highlighted_bar.py | 14 +- .../bar_chart_with_negatives.py | 9 +- .../candlestick_chart.py | 8 +- .../dot_dash_plot.py | 8 +- .../interactive_brush.py | 2 +- .../interactive_column_selection.py | 2 +- .../interactive_cross_highlight.py | 2 +- .../interactive_legend.py | 2 +- .../interactive_reorder_stacked_bars.py | 2 +- .../interval_selection_map_quakes.py | 2 +- .../examples_arguments_syntax/lasagna_plot.py | 8 +- .../layered_heatmap_text.py | 12 +- .../multiline_highlight.py | 2 +- .../multiline_tooltip.py | 5 +- .../multiline_tooltip_standard.py | 5 +- .../multiple_interactions.py | 22 +- .../scatter_linked_brush.py | 2 +- .../scatter_linked_table.py | 2 +- .../scatter_point_paths_hover.py | 20 +- .../scatter_with_histogram.py | 2 +- .../scatter_with_layered_histogram.py | 12 +- .../scatter_with_minimap.py | 2 +- .../seattle_weather_interactive.py | 4 +- .../select_detail.py | 7 +- .../selection_histogram.py | 2 +- .../selection_layer_bar_month.py | 2 +- .../selection_zorder.py | 7 +- .../slider_cutoff.py | 6 +- .../us_employment.py | 7 +- .../us_state_capitals.py | 4 +- .../waterfall_chart.py | 70 +++--- .../candlestick_chart.py | 9 +- .../interactive_column_selection.py | 2 +- .../interactive_cross_highlight.py | 2 +- .../interactive_legend.py | 2 +- .../interval_selection_map_quakes.py | 2 +- tests/examples_methods_syntax/lasagna_plot.py | 8 +- .../layered_heatmap_text.py | 13 +- .../multiline_highlight.py | 2 +- .../multiline_tooltip.py | 5 +- .../multiline_tooltip_standard.py | 5 +- .../multiple_interactions.py | 20 +- .../scatter_linked_table.py | 2 +- .../scatter_point_paths_hover.py | 20 +- .../scatter_with_layered_histogram.py | 12 +- .../scatter_with_minimap.py | 2 +- .../seattle_weather_interactive.py | 4 +- .../examples_methods_syntax/select_detail.py | 7 +- .../examples_methods_syntax/us_employment.py | 7 +- .../us_state_capitals.py | 4 +- 64 files changed, 485 insertions(+), 350 deletions(-) diff --git a/README.md b/README.md index 0e14e88265..6134975c65 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ brush = alt.selection_interval() points = alt.Chart(source).mark_point().encode( x='Horsepower', y='Miles_per_Gallon', - color=alt.condition(brush, 'Origin', alt.value('lightgray')) + color=alt.when(brush).then("Origin").otherwise(alt.value("lightgray")) ).add_params( brush ) diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index a3070acbf5..51d3f2cacd 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -913,7 +913,7 @@ def then(self, statement: _StatementType, /, **kwds: Any) -> Then[Any]: A spec or value to use when the preceding :func:`.when()` clause is true. .. note:: - ``str`` will be encoded as `shorthand`__. + ``str`` will be encoded as `shorthand`_. **kwds Additional keyword args are added to the resulting ``dict``. @@ -921,6 +921,9 @@ def then(self, statement: _StatementType, /, **kwds: Any) -> Then[Any]: ------- :class:`Then` + .. _shorthand: + https://altair-viz.github.io/user_guide/encodings/index.html#encoding-shorthands + Examples -------- Simple conditions may be expressed without defining a default:: @@ -990,10 +993,12 @@ def otherwise( Roughly equivalent to an ``else`` clause. .. note:: - ``str`` will be encoded as `shorthand`__. + ``str`` will be encoded as `shorthand`_. **kwds Additional keyword args are added to the resulting ``dict``. + .. _shorthand: + https://altair-viz.github.io/user_guide/encodings/index.html#encoding-shorthands Examples -------- @@ -1071,7 +1076,7 @@ def when( When ``predicate`` is a ``Parameter`` that is used more than once, ``alt.when().then().when(..., empty=...)`` provides granular control for each occurrence. **constraints - Specify `Field Equal Predicate `__'s. + Specify `Field Equal Predicate`_'s. Shortcut for ``alt.datum.field_name == value``, see examples for usage. Returns @@ -1079,6 +1084,8 @@ def when( :class:`ChainedWhen` A partial state which requires calling :meth:`ChainedWhen.then()` to finish the condition. + .. _Field Equal Predicate: + https://vega.github.io/vega-lite/docs/predicate.html#equal-predicate Examples -------- @@ -1176,7 +1183,7 @@ def then(self, statement: _StatementType, /, **kwds: Any) -> Then[_Conditions]: A spec or value to use when the preceding :meth:`Then.when()` clause is true. .. note:: - ``str`` will be encoded as `shorthand`__. + ``str`` will be encoded as `shorthand`_. **kwds Additional keyword args are added to the resulting ``dict``. @@ -1184,6 +1191,9 @@ def then(self, statement: _StatementType, /, **kwds: Any) -> Then[_Conditions]: ------- :class:`Then` + .. _shorthand: + https://altair-viz.github.io/user_guide/encodings/index.html#encoding-shorthands + Examples -------- Multiple conditions with an implicit default:: @@ -1247,7 +1257,7 @@ def when( When ``predicate`` is a ``Parameter`` that is used more than once, ``alt.when(..., empty=...)`` provides granular control for each occurrence. **constraints - Specify `Field Equal Predicate `__'s. + Specify `Field Equal Predicate`_'s. Shortcut for ``alt.datum.field_name == value``, see examples for usage. Returns @@ -1257,11 +1267,12 @@ def when( Notes ----- - - Directly inspired by the ``when-then-otherwise`` syntax used in ``polars.when``. + - Directly inspired by the ``when-then-otherwise`` syntax used in `polars.when`_. - References - ---------- - `polars.when `__ + .. _Field Equal Predicate: + https://vega.github.io/vega-lite/docs/predicate.html#equal-predicate + .. _polars.when: + https://docs.pola.rs/py-polars/html/reference/expressions/api/polars.when.html Examples -------- diff --git a/doc/case_studies/exploring-weather.rst b/doc/case_studies/exploring-weather.rst index bc9776787f..ad2a3bc2d0 100644 --- a/doc/case_studies/exploring-weather.rst +++ b/doc/case_studies/exploring-weather.rst @@ -226,31 +226,28 @@ of the selection (for more information on selections, see .. altair-plot:: brush = alt.selection_interval() - - points = alt.Chart().mark_point().encode( - alt.X('temp_max:Q').title('Maximum Daily Temperature (C)'), - alt.Y('temp_range:Q').title('Daily Temperature Range (C)'), - color=alt.condition(brush, 'weather:N', alt.value('lightgray'), scale=scale), - size=alt.Size('precipitation:Q').scale(range=[1, 200]) + color = alt.Color("weather:N").scale(scale) + temp_range = alt.datum["temp_max"] - alt.datum["temp_min"] + + points = alt.Chart(width=600, height=400).mark_point().encode( + alt.X("temp_max:Q").title("Maximum Daily Temperature (C)"), + alt.Y("temp_range:Q").title("Daily Temperature Range (C)"), + color=alt.when(brush).then(color).otherwise(alt.value("lightgray")), + size=alt.Size("precipitation:Q").scale(range=[1, 200]), ).transform_calculate( - "temp_range", "datum.temp_max - datum.temp_min" - ).properties( - width=600, - height=400 + temp_range=temp_range ).add_params( brush ) - bars = alt.Chart().mark_bar().encode( - x='count()', - y='weather:N', - color=alt.Color('weather:N').scale(scale), + bars = alt.Chart(width=600).mark_bar().encode( + x="count()", + y="weather:N", + color=color ).transform_calculate( - "temp_range", "datum.temp_max - datum.temp_min" + temp_range=temp_range ).transform_filter( brush - ).properties( - width=600 ) alt.vconcat(points, bars, data=df) diff --git a/doc/user_guide/compound_charts.rst b/doc/user_guide/compound_charts.rst index 503add798a..a39114d385 100644 --- a/doc/user_guide/compound_charts.rst +++ b/doc/user_guide/compound_charts.rst @@ -364,28 +364,25 @@ layered chart with a hover selection: .. altair-plot:: hover = alt.selection_point(on='pointerover', nearest=True, empty=False) + when_hover = alt.when(hover) base = alt.Chart(iris).encode( x='petalLength:Q', y='petalWidth:Q', - color=alt.condition(hover, 'species:N', alt.value('lightgray')) + color=when_hover.then("species:N").otherwise(alt.value("lightgray")) ).properties( width=180, height=180, ) - points = base.mark_point().add_params( - hover - ) + points = base.mark_point().add_params(hover) text = base.mark_text(dy=-5).encode( - text = 'species:N', - opacity = alt.condition(hover, alt.value(1), alt.value(0)) + text="species:N", + opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)), ) - alt.layer(points, text).facet( - 'species:N', - ) + (points + text).facet("species:N") Though each of the above examples have faceted the data across columns, faceting across rows (or across rows *and* columns) is supported as diff --git a/doc/user_guide/interactions/bindings_widgets.rst b/doc/user_guide/interactions/bindings_widgets.rst index dc62a6e11e..9a62307dcb 100644 --- a/doc/user_guide/interactions/bindings_widgets.rst +++ b/doc/user_guide/interactions/bindings_widgets.rst @@ -51,10 +51,10 @@ where a drop-down is used to highlight cars of a specific ``Origin``: input_dropdown = alt.binding_select(options=['Europe', 'Japan', 'USA'], name='Region ') selection = alt.selection_point(fields=['Origin'], bind=input_dropdown) - color = alt.condition( - selection, - alt.Color('Origin:N').legend(None), - alt.value('lightgray') + color = ( + alt.when(selection) + .then(alt.Color("Origin:N").legend(None)) + .otherwise(alt.value("lightgray")) ) alt.Chart(cars).mark_point().encode( @@ -72,7 +72,7 @@ and selection parameters follow the same pattern as you will see further down in the :ref:`encoding-channel-binding` section. As you can see above, -we are still using ``conditions`` to make the chart respond to the selection, +we are still using :ref:`conditions ` to make the chart respond to the selection, just as we did without widgets. Bindings and input elements can also be used to filter data allowing the user to see just the selected points as in the example below. @@ -137,11 +137,7 @@ to see the point highlighted x='Horsepower:Q', y='Miles_per_Gallon:Q', tooltip='Name:N', - opacity=alt.condition( - search_input, - alt.value(1), - alt.value(0.05) - ) + opacity=alt.when(search_input).then(alt.value(1)).otherwise(alt.value(0.05)), ).add_params( search_input ) @@ -185,16 +181,12 @@ which would have been the case if we just wrote ``xval < selector``. slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ') selector = alt.param(name='SelectorName', value=50, bind=slider) + predicate = alt.datum.xval < selector alt.Chart(df).mark_point().encode( x='xval', y='yval', - color=alt.condition( - alt.datum.xval < selector, - # 'datum.xval < SelectorName', # An equivalent alternative - alt.value('red'), - alt.value('blue') - ) + color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")), ).add_params( selector ) @@ -213,16 +205,12 @@ points based on whether they are smaller or larger than the value: bind=slider, value=[{'cutoff': 50}] ) + predicate = alt.datum.xval < selector.cutoff alt.Chart(df).mark_point().encode( x='xval', y='yval', - color=alt.condition( - alt.datum.xval < selector.cutoff, - # 'datum.xval < SelectorName.cutoff', # An equivalent alternative - alt.value('red'), - alt.value('blue') - ) + color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")), ).add_params( selector ) @@ -263,11 +251,7 @@ just if the value of the check box is True (checked) or False (unchecked): alt.Chart(cars).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - size=alt.condition( - param_checkbox, - 'Acceleration:Q', - alt.value(25) - ) + size=alt.when(param_checkbox).then("Acceleration:Q").otherwise(alt.value(25)), ).add_params( param_checkbox ) @@ -315,7 +299,7 @@ Altair provides the ``bind='legend'`` option to facilitate the creation of click x='Horsepower:Q', y='Miles_per_Gallon:Q', color='Origin:N', - opacity=alt.condition(selection, alt.value(0.8), alt.value(0.2)) + opacity=alt.when(selection).then(alt.value(0.8)).otherwise(alt.value(0.2)), ).add_params( selection ) diff --git a/doc/user_guide/interactions/expressions.rst b/doc/user_guide/interactions/expressions.rst index a73751ef43..a4e9440abd 100644 --- a/doc/user_guide/interactions/expressions.rst +++ b/doc/user_guide/interactions/expressions.rst @@ -169,19 +169,14 @@ To try this out, you can type ``mazda|ford`` in the search input box below. name='Search ', ) ) + search_matches = alt.expr.test(alt.expr.regexp(search_input, "i"), alt.datum.Name) + alt.Chart(cars).mark_point(size=60).encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', tooltip='Name:N', - opacity=alt.condition( - alt.expr.test(alt.expr.regexp(search_input, 'i'), alt.datum.Name), - # f"test(regexp({search_input.name}, 'i'), datum.Name)", # Equivalent js alternative - alt.value(1), - alt.value(0.05) - ) - ).add_params( - search_input - ) + opacity=alt.when(search_matches).then(alt.value(1)).otherwise(alt.value(0.05)), + ).add_params(search_input) And remember, all this interactivity is client side. You can save this chart as an HTML file or put it on a static site generator such as GitHub/GitLab pages diff --git a/doc/user_guide/interactions/jupyter_chart.rst b/doc/user_guide/interactions/jupyter_chart.rst index 88982c06bb..a4ad028d1e 100644 --- a/doc/user_guide/interactions/jupyter_chart.rst +++ b/doc/user_guide/interactions/jupyter_chart.rst @@ -105,14 +105,12 @@ is available as ``jchart.params.cutoff``. slider = alt.binding_range(min=0, max=100, step=1) cutoff = alt.param(name="cutoff", bind=slider, value=50) + predicate = alt.datum.xval < cutoff chart = alt.Chart(df).mark_point().encode( x='xval', y='yval', - color=alt.condition( - alt.datum.xval < cutoff, - alt.value('red'), alt.value('blue') - ) + color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")), ).add_params( cutoff ) @@ -201,14 +199,12 @@ variable's value only from the ``IntSlider`` ipywidget. }) cutoff = alt.param(name="cutoff", value=50) + predicate = alt.datum.xval < cutoff chart = alt.Chart(df).mark_point().encode( x='xval', y='yval', - color=alt.condition( - alt.datum.xval < cutoff, - alt.value('red'), alt.value('blue') - ) + color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")) ).add_params( cutoff ) @@ -253,7 +249,7 @@ the legend. chart = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('grey')), + color=alt.when(brush).then("Origin:N").otherwise(alt.value("grey")), ).add_params(brush) jchart = alt.JupyterChart(chart) @@ -306,7 +302,7 @@ extract the selected rows in the input DataFrame. chart = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('grey')), + color=alt.when(brush).then("Origin:N").otherwise(alt.value("grey")), ).add_params(brush) jchart = alt.JupyterChart(chart) @@ -344,7 +340,7 @@ is a dictionary from column names to selection intervals chart = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Cylinders:O', alt.value('grey')), + color=alt.when(brush).then("Cylinders:O").otherwise(alt.value("grey")), ).add_params(brush) jchart = alt.JupyterChart(chart) @@ -399,7 +395,7 @@ is used to combine the chart and HTML table in a column layout. chart_widget = alt.JupyterChart(alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Cylinders:O', alt.value('grey')), + color=alt.when(brush).then("Cylinders:O").otherwise(alt.value("grey")), ).add_params(brush)) table_widget = HTML(value=source.iloc[:0].to_html()) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 1dce8c116f..cf42d572bf 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -3,7 +3,10 @@ .. _parameters: Parameters, Conditions, & Filters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================= + +Parameters +~~~~~~~~~~ Parameters are the building blocks of interaction in Altair. There are two types of parameters: *variables* and *selections*. We introduce these concepts through a series of examples. @@ -146,25 +149,29 @@ we created a selection parameter using ``brush = alt.selection_interval()``, and we attached that parameter to the chart using ``add_params``. One difference is that here we have not defined how the chart should respond to the selection; you will learn this in the next section. -Conditions & Filters -~~~~~~~~~~~~~~~~~~~~ +.. _conditions: -Conditional Encodings -^^^^^^^^^^^^^^^^^^^^^ +Conditions +~~~~~~~~~~ + +.. note:: + + This material was changed considerably with the release of Altair ``5.5.0``. + :func:`when` was introduced in ``5.4.0`` and should be preferred over :func:`condition`. The example above is neat, but the selection interval doesn't actually *do* anything yet. -To make the chart respond to this selection, we need to reference the selection in within -the chart specification. Here, we will use the :func:`condition` function to create -a conditional color encoding: we'll tie the color to the ``"Origin"`` -column for points in the selection, and set the color to ``"lightgray"`` -for points outside the selection: +To make the chart respond to this selection, we need to reference ``brush`` within +the chart specification. Here, we will use the :func:`when` function to create +a conditional color encoding: .. altair-plot:: + conditional = alt.when(brush).then("Origin:N").otherwise(alt.value("lightgray")) + alt.Chart(cars).mark_point().encode( - x='Horsepower:Q', - y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('lightgray')) + x="Horsepower:Q", + y="Miles_per_Gallon:Q", + color=conditional, ).add_params( brush ) @@ -172,16 +179,68 @@ for points outside the selection: As you can see, the color of the points now changes depending on whether they are inside or outside the selection. Above we are using the selection parameter ``brush`` as a *predicate* (something that evaluates as `True` or `False`). -This is controlled by the line ``color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))``. + +This is controlled by our definition ``conditional``:: + + conditional = alt.when(brush).then("Origin:N").otherwise(alt.value("lightgray")) + Data points which fall within the selection evaluate as ``True``, and data points which fall outside the selection evaluate to ``False``. -The ``'Origin:N'`` specifies how to color the points which fall within the selection, -and the ``alt.value('lightgray')`` specifies that the outside points should be given a constant color value; -you can remember this as ``alt.condition(, , )``. +The ``"Origin:N"`` specifies how to color the points which fall within the selection, +and the ``alt.value('lightgray')`` specifies that the outside points should be given a constant color value. + +Understanding :func:`when` +^^^^^^^^^^^^^^^^^^^^^^^^^^ -This approach becomes even more powerful when the selection behavior is +The ``when-then-otherwise`` syntax was directly inspired by `polars.when`_, +and is similar to an ``if-else`` statement written in Python:: + + # alt.when(brush) + if brush: + # .then("Origin:N") + color = "Origin:N" + else: + # .otherwise(alt.value("lightgray")) + color = alt.value("lightgray") + +Omitting the ``.otherwise()`` clause will use the channel default instead: + +.. altair-plot:: + + source = data.cars() + brush = alt.selection_interval() + + points = alt.Chart(source).mark_point().encode( + x="Horsepower", + y="Miles_per_Gallon", + color=alt.when(brush).then(alt.value("goldenrod")) + ).add_params( + brush + ) + + points + +Multiple conditional branches (``if, elif, ..., elif`` in Python) +are expressed via chained calls to :func:`when`. +You will see an example with working code in :ref:`conditional-branches` +when you have learned about different selection types. + +More advanced use of conditions can be found +in the :func:`when` API reference +and in these gallery examples: + +- :ref:`gallery_dot_dash_plot` +- :ref:`gallery_interactive_bar_select_highlight` +- :ref:`gallery_multiline_tooltip_standard` +- :ref:`gallery_scatter_point_paths_hover` +- :ref:`gallery_waterfall_chart` + +Linking Conditions Across Charts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Conditional encodings become even more powerful when the selection behavior is tied across multiple views of the data within a compound chart. -For example, here we create a ``chart`` object using the same code as +For example, here we create a :class:`Chart` using the same code as above, and horizontally concatenate two versions of this chart: one with the x-encoding tied to ``"Horsepower"``, and one with the x-encoding tied to ``"Acceleration"`` @@ -191,7 +250,7 @@ tied to ``"Acceleration"`` chart = alt.Chart(cars).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('lightgray')) + color=alt.when(brush).then("Origin:N").otherwise(alt.value("lightgray")), ).properties( width=250, height=250 @@ -218,7 +277,7 @@ We can modify the brush definition, and leave the rest of the code unchanged: chart = alt.Chart(cars).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('lightgray')) + color=alt.when(brush).then("Origin:N").otherwise(alt.value("lightgray")), ).properties( width=250, height=250 @@ -231,15 +290,18 @@ We can modify the brush definition, and leave the rest of the code unchanged: As you might have noticed, the selected points are sometimes obscured by some of the unselected points. To bring the selected points to the foreground, -we can change the order in which they are laid out via the following -encoding: ``order=alt.condition(hover, alt.value(1), alt.value(0))``. -You can see an example of this in the :ref:`gallery_selection_zorder` gallery example. +we can change the order in which they are laid out via the following encoding:: -Filtering Data -^^^^^^^^^^^^^^ + hover = alt.selection_point(on='pointerover', nearest=True, empty=False) + order = alt.when(hover).then(alt.value(1)).otherwise(alt.value(0)) + + + +Filters +~~~~~~~ Using a selection parameter to filter data works in much the same way -as using it within ``condition``. +as using it within :func:`when`. For example, in ``transform_filter(brush)``, we are again using the selection parameter ``brush`` as a predicate. Data points which evaluate to ``True`` (i.e., data points which lie within the selection) are kept, @@ -296,7 +358,7 @@ selection: return alt.Chart(cars).mark_rect().encode( x="Cylinders:O", y="Origin:N", - color=alt.condition(selector, 'count()', alt.value('lightgray')) + color=alt.when(selector).then("count()").otherwise(alt.value("lightgray")), ).properties( width=300, height=180 @@ -328,6 +390,16 @@ empty selection contains none of the points: interval_x = alt.selection_interval(encodings=['x'], empty=False) make_example(interval_x) +The ``empty=False`` argument could instead be set inside :func:`when`, +to change the behavior of each condition when an empty selection is passed, +rather than having to define separate selection objects:: + + brush = alt.selection_interval() + ... + color=alt.when(brush).then(...) + size=alt.when(brush, empty=False).then(...) + ... + Point Selections ^^^^^^^^^^^^^^^^ A *point* selection allows you to select chart elements one at a time @@ -367,10 +439,10 @@ with a matching ``Origin``. .. altair-plot:: selection = alt.selection_point(fields=['Origin']) - color = alt.condition( - selection, - alt.Color('Origin:N').legend(None), - alt.value('lightgray') + color = ( + alt.when(selection) + .then(alt.Color("Origin:N").legend(None)) + .otherwise(alt.value("lightgray")) ) scatter = alt.Chart(cars).mark_point().encode( @@ -402,10 +474,10 @@ cylinders: .. altair-plot:: selection = alt.selection_point(fields=['Origin', 'Cylinders']) - color = alt.condition( - selection, - alt.Color('Origin:N').legend(None), - alt.value('lightgray') + color = ( + alt.when(selection) + .then(alt.Color("Origin:N").legend(None)) + .otherwise(alt.value("lightgray")) ) scatter = alt.Chart(cars).mark_point().encode( @@ -428,9 +500,85 @@ cylinders: By fine-tuning the behavior of selections in this way, they can be used to create a wide variety of linked interactive chart types. +Combining Parameters +~~~~~~~~~~~~~~~~~~~~ + +Multiple parameters can be combined in a single chart, +either via multiple separate response conditions, +different conditional branches in :func:`when`, +or parameter composition. + +Multiple conditions +^^^^^^^^^^^^^^^^^^^ + +In this example, +points that are hovered with the pointer +will increase in size +and those that are clicked +will be filled in with red. +The ``empty=False`` is to ensure that no points are selected to start. +Try holding shift to select multiple points on either hover or click. + +.. altair-plot:: + + click = alt.selection_point(empty=False) + hover = alt.selection_point(on='pointerover', empty=False) + + points = alt.Chart(cars).mark_point().encode( + x='Horsepower:Q', + y='Miles_per_Gallon:Q', + fill=alt.when(click).then(alt.value('red')), + size=alt.when(hover).then(alt.value(1000)) + ).add_params( + click, hover + ) + + points + +.. _conditional-branches: + +Conditional branches +^^^^^^^^^^^^^^^^^^^^ + +:func:`when` allows the use of multiple ``then`` (``elif``) branches +which can change the behavior of a single encoding +in response to multiple different parameters. +Here, +we fill hovered points in yellow, +before changing the fill to red +when a point is clicked. +Since the mouse is hovering over points +while clicking them, +both conditions will be active +and the earlier branch takes precedence +(you can try by changing the order of the two ``when.then`` clauses +and observing that the points will not change to red when clicked). + +.. altair-plot:: + + click = alt.selection_point(empty=False) + hover = alt.selection_point(on='pointerover', empty=False) + + points = alt.Chart(cars).mark_point().encode( + x='Horsepower:Q', + y='Miles_per_Gallon:Q', + fill=( + alt.when(click) + .then(alt.value('red')) + .when(hover) + .then(alt.value('gold')) + ), + size=alt.when(hover).then(alt.value(1000)) + ).add_params( + click, hover + ) + + points + +.. _parameter-composition: Parameter Composition -~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^ Altair also supports combining multiple parameters using the ``&``, ``|`` and ``~`` for respectively ``AND``, ``OR`` and ``NOT`` logical composition @@ -462,7 +610,7 @@ selection alt.Chart(cars).mark_rect().encode( x='Cylinders:O', y='Origin:O', - color=alt.condition(alex | morgan, 'count()', alt.ColorValue("grey")) + color=alt.when(alex | morgan).then("count()").otherwise(alt.value("grey")), ).add_params( alex, morgan ).properties( @@ -482,3 +630,5 @@ For more information on how to fine-tune selections, including specifying other mouse and keystroke options, see the `Vega-Lite Selection documentation `_. +.. _polars.when: + https://docs.pola.rs/py-polars/html/reference/expressions/api/polars.when.html diff --git a/doc/user_guide/marks/geoshape.rst b/doc/user_guide/marks/geoshape.rst index 4db48f98c8..4c612ca613 100644 --- a/doc/user_guide/marks/geoshape.rst +++ b/doc/user_guide/marks/geoshape.rst @@ -529,9 +529,10 @@ populous states. Using an ``alt.selection_point()`` we define a selection parame # define a pointer selection click_state = alt.selection_point(fields=["state"]) + # define a condition on the opacity encoding depending on the selection + opacity = alt.when(click_state).then(alt.value(1)).otherwise(alt.value(0.2)) # create a choropleth map using a lookup transform - # define a condition on the opacity encoding depending on the selection choropleth = ( alt.Chart(us_states) .mark_geoshape() @@ -540,13 +541,13 @@ populous states. Using an ``alt.selection_point()`` we define a selection parame ) .encode( color="population:Q", - opacity=alt.condition(click_state, alt.value(1), alt.value(0.2)), + opacity=opacity, tooltip=["state:N", "population:Q"], ) .project(type="albersUsa") ) - # create a bar chart with a similar condition on the opacity encoding. + # create a bar chart with the same conditional ``opacity`` encoding. bars = ( alt.Chart( us_population.nlargest(15, "population"), title="Top 15 states by population" @@ -554,7 +555,7 @@ populous states. Using an ``alt.selection_point()`` we define a selection parame .mark_bar() .encode( x="population", - opacity=alt.condition(click_state, alt.value(1), alt.value(0.2)), + opacity=opacity, color="population", y=alt.Y("state").sort("-x"), ) @@ -616,7 +617,7 @@ We use here an elegant way to access the nested point coordinates from the geome .encode( longitude="lon:Q", latitude="lat:Q", - strokeWidth=alt.condition(hover, alt.value(1, empty=False), alt.value(0)), + strokeWidth=alt.when(hover, empty=False).then(alt.value(1)).otherwise(alt.value(0)), size=alt.Size( "mag:Q", scale=alt.Scale(type="pow", range=[1, 1000], domain=[0, 6], exponent=4), diff --git a/doc/user_guide/marks/line.rst b/doc/user_guide/marks/line.rst index 13f638f25f..feda5bbf53 100644 --- a/doc/user_guide/marks/line.rst +++ b/doc/user_guide/marks/line.rst @@ -139,7 +139,7 @@ We can further apply selection to highlight a certain line on hover. ) lines = base.mark_line().encode( - size=alt.condition(~highlight, alt.value(1), alt.value(3)) + size=alt.when(~highlight).then(alt.value(1)).otherwise(alt.value(3)) ) points + lines diff --git a/doc/user_guide/marks/text.rst b/doc/user_guide/marks/text.rst index 4bae2f8b51..35d363fceb 100644 --- a/doc/user_guide/marks/text.rst +++ b/doc/user_guide/marks/text.rst @@ -127,13 +127,10 @@ Text Table Heatmap .legend(direction="horizontal") ) + predicate = alt.datum.num_cars > 100 text = base.mark_text(baseline="middle").encode( text="num_cars:Q", - color=alt.condition( - alt.datum.num_cars > 100, - alt.value("black"), - alt.value("white"), - ), + color=alt.when(predicate).then(alt.value("black")).otherwise(alt.value("white")), ) heatmap + text diff --git a/doc/user_guide/times_and_dates.rst b/doc/user_guide/times_and_dates.rst index a8cd47ab3c..98ad9390ca 100644 --- a/doc/user_guide/times_and_dates.rst +++ b/doc/user_guide/times_and_dates.rst @@ -187,12 +187,13 @@ way that Altair expects: df = pd.DataFrame({'local': ['2018-01-01T00:00:00'], 'utc': ['2018-01-01T00:00:00Z']}) + when_compliant = alt.when(compliant=True) alt.Chart(df).transform_calculate( compliant="hours(datum.local) != hours(datum.utc) ? true : false", - ).mark_text(size=20, baseline='middle').encode( - text=alt.condition('datum.compliant', alt.value('OK'), alt.value('not OK')), - color=alt.condition('datum.compliant', alt.value('green'), alt.value('red')) + ).mark_text(size=20, baseline="middle").encode( + text=when_compliant.then(alt.value("OK")).otherwise(alt.value("not OK")), + color=when_compliant.then(alt.value("green")).otherwise(alt.value("red")), ).properties(width=80, height=50) If the above output contains a red "not OK": diff --git a/doc/user_guide/transform/filter.rst b/doc/user_guide/transform/filter.rst index 3fca3f1963..fb4c7420fd 100644 --- a/doc/user_guide/transform/filter.rst +++ b/doc/user_guide/transform/filter.rst @@ -135,30 +135,24 @@ to select the data to be shown in the top chart: selection = alt.selection_point(fields=['year']) - top = alt.Chart().mark_line().encode( - x='age:O', - y='sum(people):Q', - color='year:O' - ).properties( - width=600, height=200 + top = alt.Chart(width=600, height=200).mark_line().encode( + x="age:O", + y="sum(people):Q", + color="year:O" ).transform_filter( selection ) - bottom = alt.Chart().mark_bar().encode( - x='year:O', - y='sum(people):Q', - color=alt.condition(selection, alt.value('steelblue'), alt.value('lightgray')) - ).properties( - width=600, height=100 + color = alt.when(selection).then(alt.value("steelblue")).otherwise(alt.value("lightgray")) + bottom = alt.Chart(width=600, height=100).mark_bar().encode( + x="year:O", + y="sum(people):Q", + color=color ).add_params( selection ) - alt.vconcat( - top, bottom, - data=pop - ) + alt.vconcat(top, bottom, data=pop) Logical Operands ^^^^^^^^^^^^^^^^ diff --git a/doc/user_guide/transform/pivot.rst b/doc/user_guide/transform/pivot.rst index eb3746c731..eb280d1e5a 100644 --- a/doc/user_guide/transform/pivot.rst +++ b/doc/user_guide/transform/pivot.rst @@ -43,27 +43,27 @@ values on multiple lines: .. altair-plot:: - import altair as alt - from vega_datasets import data + import altair as alt + from vega_datasets import data - source = data.stocks() - base = alt.Chart(source).encode(x='date:T') - columns = sorted(source.symbol.unique()) - selection = alt.selection_point( - fields=['date'], nearest=True, on='pointerover', empty=False, clear='pointerout' - ) + source = data.stocks() + base = alt.Chart(source).encode(x='date:T') + columns = sorted(source.symbol.unique()) + selection = alt.selection_point( + fields=['date'], nearest=True, on='pointerover', empty=False, clear='pointerout' + ) - lines = base.mark_line().encode(y='price:Q', color='symbol:N') - points = lines.mark_point().transform_filter(selection) + lines = base.mark_line().encode(y='price:Q', color='symbol:N') + points = lines.mark_point().transform_filter(selection) rule = base.transform_pivot( 'symbol', value='price', groupby=['date'] ).mark_rule().encode( - opacity=alt.condition(selection, alt.value(0.3), alt.value(0)), + opacity=alt.when(selection).then(alt.value(0.3)).otherwise(alt.value(0)), tooltip=[alt.Tooltip(c, type='quantitative') for c in columns] ).add_params(selection) - lines + points + rule + lines + points + rule Transform Options diff --git a/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py b/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py index d277bf9f3e..1041fb99fc 100644 --- a/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py +++ b/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py @@ -9,13 +9,13 @@ source = data.wheat() +# If the `year` column equals `1810` +# then, set the bar color to `"orange"` +# otherwise, use `"steelblue"` +color = alt.when(year=1810).then(alt.value("orange")).otherwise(alt.value("steelblue")) + alt.Chart(source).mark_bar().encode( - x='year:O', + x="year:O", y="wheat:Q", - # The highlight will be set on the result of a conditional statement - color=alt.condition( - alt.datum.year == 1810, # If the year is 1810 this test returns True, - alt.value('orange'), # which sets the bar orange. - alt.value('steelblue') # And if it's not true it sets the bar steelblue. - ) + color=color ).properties(width=600) diff --git a/tests/examples_arguments_syntax/bar_chart_with_negatives.py b/tests/examples_arguments_syntax/bar_chart_with_negatives.py index 127a16ba4f..d3ff3fbc58 100644 --- a/tests/examples_arguments_syntax/bar_chart_with_negatives.py +++ b/tests/examples_arguments_syntax/bar_chart_with_negatives.py @@ -9,12 +9,11 @@ source = data.us_employment() +predicate = alt.datum.nonfarm_change > 0 +color = alt.when(predicate).then(alt.value("steelblue")).otherwise(alt.value("orange")) + alt.Chart(source).mark_bar().encode( x="month:T", y="nonfarm_change:Q", - color=alt.condition( - alt.datum.nonfarm_change > 0, - alt.value("steelblue"), # The positive color - alt.value("orange") # The negative color - ) + color=color ).properties(width=600) diff --git a/tests/examples_arguments_syntax/candlestick_chart.py b/tests/examples_arguments_syntax/candlestick_chart.py index 23b338b8e4..4dc5247825 100644 --- a/tests/examples_arguments_syntax/candlestick_chart.py +++ b/tests/examples_arguments_syntax/candlestick_chart.py @@ -12,9 +12,11 @@ source = data.ohlc() -open_close_color = alt.condition("datum.open <= datum.close", - alt.value("#06982d"), - alt.value("#ae1325")) +open_close_color = ( + alt.when("datum.open <= datum.close") + .then(alt.value("#06982d")) + .otherwise(alt.value("#ae1325")) +) base = alt.Chart(source).encode( alt.X('date:T', diff --git a/tests/examples_arguments_syntax/dot_dash_plot.py b/tests/examples_arguments_syntax/dot_dash_plot.py index 72d73d2e8b..64c6ef4506 100644 --- a/tests/examples_arguments_syntax/dot_dash_plot.py +++ b/tests/examples_arguments_syntax/dot_dash_plot.py @@ -12,28 +12,30 @@ # Configure the options common to all layers brush = alt.selection_interval() +brush_origin = alt.when(brush).then("Origin") base = alt.Chart(source).add_params(brush) # Configure the points points = base.mark_point().encode( x=alt.X('Miles_per_Gallon', title=''), y=alt.Y('Horsepower', title=''), - color=alt.condition(brush, 'Origin', alt.value('grey')) + color=brush_origin.otherwise(alt.value("grey")), ) # Configure the ticks tick_axis = alt.Axis(labels=False, domain=False, ticks=False) +tick_color = brush_origin.otherwise(alt.value("lightgrey")) x_ticks = base.mark_tick().encode( alt.X('Miles_per_Gallon', axis=tick_axis), alt.Y('Origin', title='', axis=tick_axis), - color=alt.condition(brush, 'Origin', alt.value('lightgrey')) + color=tick_color ) y_ticks = base.mark_tick().encode( alt.X('Origin', title='', axis=tick_axis), alt.Y('Horsepower', axis=tick_axis), - color=alt.condition(brush, 'Origin', alt.value('lightgrey')) + color=tick_color ) # Build the chart diff --git a/tests/examples_arguments_syntax/interactive_brush.py b/tests/examples_arguments_syntax/interactive_brush.py index 2cfd66037d..bee087c579 100644 --- a/tests/examples_arguments_syntax/interactive_brush.py +++ b/tests/examples_arguments_syntax/interactive_brush.py @@ -15,5 +15,5 @@ alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Cylinders:O', alt.value('grey')), + color=alt.when(brush).then("Cylinders:O").otherwise(alt.value("grey")), ).add_params(brush) diff --git a/tests/examples_arguments_syntax/interactive_column_selection.py b/tests/examples_arguments_syntax/interactive_column_selection.py index 1c82aad8f0..0fa4826aa9 100644 --- a/tests/examples_arguments_syntax/interactive_column_selection.py +++ b/tests/examples_arguments_syntax/interactive_column_selection.py @@ -37,7 +37,7 @@ alt.X('level_0', title=None), alt.Y('level_1', title=None), alt.Color('correlation', scale=alt.Scale(domain=[-1, 1], scheme='blueorange')), - opacity=alt.condition(select_x & select_y, alt.value(1), alt.value(0.4)) + opacity=alt.when(select_x, select_y).then(alt.value(1)).otherwise(alt.value(0.4)), ).add_params( select_x, select_y ) diff --git a/tests/examples_arguments_syntax/interactive_cross_highlight.py b/tests/examples_arguments_syntax/interactive_cross_highlight.py index 796dc31107..f2b7e2d2ae 100644 --- a/tests/examples_arguments_syntax/interactive_cross_highlight.py +++ b/tests/examples_arguments_syntax/interactive_cross_highlight.py @@ -34,7 +34,7 @@ bar = alt.Chart(source).mark_bar().encode( x='Major_Genre:N', y='count()', - color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey")) + color=alt.when(pts).then(alt.ColorValue("steelblue")).otherwise(alt.ColorValue("grey")) ).properties( width=550, height=200 diff --git a/tests/examples_arguments_syntax/interactive_legend.py b/tests/examples_arguments_syntax/interactive_legend.py index bd8b14b1a8..61e45f44dc 100644 --- a/tests/examples_arguments_syntax/interactive_legend.py +++ b/tests/examples_arguments_syntax/interactive_legend.py @@ -17,7 +17,7 @@ alt.X('yearmonth(date):T', axis=alt.Axis(domain=False, format='%Y', tickSize=0)), alt.Y('sum(count):Q', stack='center', axis=None), alt.Color('series:N', scale=alt.Scale(scheme='category20b')), - opacity=alt.condition(selection, alt.value(1), alt.value(0.2)) + opacity=alt.when(selection).then(alt.value(1)).otherwise(alt.value(0.2)) ).add_params( selection ) diff --git a/tests/examples_arguments_syntax/interactive_reorder_stacked_bars.py b/tests/examples_arguments_syntax/interactive_reorder_stacked_bars.py index 606bc37a15..2fbed1dcae 100644 --- a/tests/examples_arguments_syntax/interactive_reorder_stacked_bars.py +++ b/tests/examples_arguments_syntax/interactive_reorder_stacked_bars.py @@ -25,7 +25,7 @@ y='variety:N', color='site:N', order='site_order:N', - opacity=alt.condition(selection, alt.value(0.9), alt.value(0.2)) + opacity=alt.when(selection).then(alt.value(0.9)).otherwise(alt.value(0.2)) ).add_params( selection ) diff --git a/tests/examples_arguments_syntax/interval_selection_map_quakes.py b/tests/examples_arguments_syntax/interval_selection_map_quakes.py index 6ab6bed8d9..3a2d71c862 100644 --- a/tests/examples_arguments_syntax/interval_selection_map_quakes.py +++ b/tests/examples_arguments_syntax/interval_selection_map_quakes.py @@ -38,7 +38,7 @@ ).mark_circle(opacity=0.35, tooltip=True).encode( longitude="lon:Q", latitude="lat:Q", - color=alt.condition(brush, alt.value("goldenrod"), alt.value("steelblue")), + color=alt.when(brush).then(alt.value("goldenrod")).otherwise(alt.value("steelblue")), size=alt.Size("mag:Q", scale=alt.Scale(type="pow", range=[1, 1000], domain=[0, 7], exponent=4)), ).add_params(brush) diff --git a/tests/examples_arguments_syntax/lasagna_plot.py b/tests/examples_arguments_syntax/lasagna_plot.py index 6f603b8e18..d3e60ed34e 100644 --- a/tests/examples_arguments_syntax/lasagna_plot.py +++ b/tests/examples_arguments_syntax/lasagna_plot.py @@ -8,10 +8,10 @@ source = data.stocks() -color_condition = alt.condition( - "month(datum.value) == 1 && date(datum.value) == 1", - alt.value("black"), - alt.value(None), +color_condition = ( + alt.when(alt.expr.month("datum.value") == 1, alt.expr.date("datum.value") == 1) + .then(alt.value("black")) + .otherwise(alt.value(None)) ) alt.Chart(source, width=300, height=100).transform_filter( diff --git a/tests/examples_arguments_syntax/layered_heatmap_text.py b/tests/examples_arguments_syntax/layered_heatmap_text.py index dc912ed8b0..7dec0fd266 100644 --- a/tests/examples_arguments_syntax/layered_heatmap_text.py +++ b/tests/examples_arguments_syntax/layered_heatmap_text.py @@ -28,14 +28,14 @@ ) ) +color = ( + alt.when(alt.datum.mean_horsepower > 150) + .then(alt.value("black")) + .otherwise(alt.value("white")) +) # Configure text text = base.mark_text(baseline='middle').encode( - text=alt.Text('mean_horsepower:Q', format=".0f"), - color=alt.condition( - alt.datum.mean_horsepower > 150, - alt.value('black'), - alt.value('white') - ) + text=alt.Text('mean_horsepower:Q', format=".0f"), color=color ) # Draw the chart diff --git a/tests/examples_arguments_syntax/multiline_highlight.py b/tests/examples_arguments_syntax/multiline_highlight.py index 5da8415163..575c880818 100644 --- a/tests/examples_arguments_syntax/multiline_highlight.py +++ b/tests/examples_arguments_syntax/multiline_highlight.py @@ -30,7 +30,7 @@ ) lines = base.mark_line().encode( - size=alt.condition(~highlight, alt.value(1), alt.value(3)) + size=alt.when(~highlight).then(alt.value(1)).otherwise(alt.value(3)) ) points + lines diff --git a/tests/examples_arguments_syntax/multiline_tooltip.py b/tests/examples_arguments_syntax/multiline_tooltip.py index 12ac92bf0d..d2bd7ff8f5 100644 --- a/tests/examples_arguments_syntax/multiline_tooltip.py +++ b/tests/examples_arguments_syntax/multiline_tooltip.py @@ -41,15 +41,16 @@ ).add_params( nearest ) +when_near = alt.when(nearest) # Draw points on the line, and highlight based on selection points = line.mark_point().encode( - opacity=alt.condition(nearest, alt.value(1), alt.value(0)) + opacity=when_near.then(alt.value(1)).otherwise(alt.value(0)) ) # Draw text labels near the points, and highlight based on selection text = line.mark_text(align="left", dx=5, dy=-5).encode( - text=alt.condition(nearest, "y:Q", alt.value(" ")) + text=when_near.then("y:Q").otherwise(alt.value(" ")) ) # Draw a rule at the location of the selection diff --git a/tests/examples_arguments_syntax/multiline_tooltip_standard.py b/tests/examples_arguments_syntax/multiline_tooltip_standard.py index 990aa20150..bbab79d46a 100644 --- a/tests/examples_arguments_syntax/multiline_tooltip_standard.py +++ b/tests/examples_arguments_syntax/multiline_tooltip_standard.py @@ -28,10 +28,11 @@ y="y:Q", color="category:N" ) +when_near = alt.when(nearest) # Draw points on the line, and highlight based on selection points = line.mark_point().encode( - opacity=alt.condition(nearest, alt.value(1), alt.value(0)) + opacity=when_near.then(alt.value(1)).otherwise(alt.value(0)) ) # Draw a rule at the location of the selection @@ -41,7 +42,7 @@ groupby=["x"] ).mark_rule(color="gray").encode( x="x:Q", - opacity=alt.condition(nearest, alt.value(0.3), alt.value(0)), + opacity=when_near.then(alt.value(0.3)).otherwise(alt.value(0)), tooltip=[alt.Tooltip(c, type="quantitative") for c in columns], ).add_params(nearest) diff --git a/tests/examples_arguments_syntax/multiple_interactions.py b/tests/examples_arguments_syntax/multiple_interactions.py index 8fbc4281e0..96bfb8fed5 100644 --- a/tests/examples_arguments_syntax/multiple_interactions.py +++ b/tests/examples_arguments_syntax/multiple_interactions.py @@ -61,32 +61,32 @@ rating_radio = alt.binding_radio(options=ratings, name="Rating") rating_select = alt.selection_point(fields=['MPAA_Rating'], bind=rating_radio) -rating_color_condition = alt.condition( - rating_select, - alt.Color('MPAA_Rating:N', legend=None), - alt.value('lightgray') +rating_color = ( + alt.when(rating_select) + .then(alt.Color('MPAA_Rating:N', legend=None)) + .otherwise(alt.value("lightgray")) ) highlight_ratings = base.add_params( rating_select ).encode( - color=rating_color_condition + color=rating_color ).properties(title="Radio Button Highlighting") # Boolean selection for format changes input_checkbox = alt.binding_checkbox(name="Big Budget Films ") checkbox_selection = alt.param(bind=input_checkbox) -size_checkbox_condition = alt.condition( - checkbox_selection, - alt.Size('Hundred_Million_Production:Q'), - alt.SizeValue(25) +size_checkbox = ( + alt.when(checkbox_selection) + .then(alt.Size('Big_Budget_Film:N', scale=alt.Scale(range=[25, 150]))) + .otherwise(alt.value(25)) ) budget_sizing = base.add_params( checkbox_selection ).encode( - size=size_checkbox_condition + size=size_checkbox ).properties(title="Checkbox Formatting") -(filter_year | filter_genres) & (highlight_ratings | budget_sizing) +(filter_year | budget_sizing) & (highlight_ratings | filter_genres) diff --git a/tests/examples_arguments_syntax/scatter_linked_brush.py b/tests/examples_arguments_syntax/scatter_linked_brush.py index adf88d34bb..b8548fd020 100644 --- a/tests/examples_arguments_syntax/scatter_linked_brush.py +++ b/tests/examples_arguments_syntax/scatter_linked_brush.py @@ -14,7 +14,7 @@ base = alt.Chart(source).mark_point().encode( y='Miles_per_Gallon', - color=alt.condition(brush, 'Origin', alt.ColorValue('gray')), + color=alt.when(brush).then("Origin").otherwise(alt.ColorValue("gray")), ).add_params( brush ).properties( diff --git a/tests/examples_arguments_syntax/scatter_linked_table.py b/tests/examples_arguments_syntax/scatter_linked_table.py index 93777b7518..e17c4dbb02 100644 --- a/tests/examples_arguments_syntax/scatter_linked_table.py +++ b/tests/examples_arguments_syntax/scatter_linked_table.py @@ -18,7 +18,7 @@ points = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, alt.value('steelblue'), alt.value('grey')) + color=alt.when(brush).then(alt.value("steelblue")).otherwise(alt.value("grey")) ).add_params(brush) # Base chart for data tables diff --git a/tests/examples_arguments_syntax/scatter_point_paths_hover.py b/tests/examples_arguments_syntax/scatter_point_paths_hover.py index ee755b9e07..aea0960f68 100644 --- a/tests/examples_arguments_syntax/scatter_point_paths_hover.py +++ b/tests/examples_arguments_syntax/scatter_point_paths_hover.py @@ -53,14 +53,15 @@ "datum.country !== 'North Korea' && datum.country !== 'South Korea'" ) +search_matches = alt.expr.test(alt.expr.regexp(search_box, "i"), alt.datum.country) +opacity = ( + alt.when(hover_point_opacity, search_matches) + .then(alt.value(0.8)) + .otherwise(alt.value(0.1)) +) # Points that are always visible (filtered by slider and search) visible_points = base.mark_circle(size=100).encode( - opacity=alt.condition( - hover_point_opacity - & alt.expr.test(alt.expr.regexp(search_box, 'i'), alt.datum.country), - alt.value(0.8), - alt.value(0.1) - ) + opacity=opacity ).transform_filter( x_select ).add_params( @@ -69,6 +70,7 @@ x_select ) +when_hover = alt.when(hover) hover_line = alt.layer( # Line layer base.mark_trail().encode( @@ -81,12 +83,12 @@ scale=alt.Scale(domain=[1955, 2005], range=[1, 12]), legend=None ), - opacity=alt.condition(hover, alt.value(0.3), alt.value(0)), + opacity=when_hover.then(alt.value(0.3)).otherwise(alt.value(0)), color=alt.value('#222222') ), # Point layer base.mark_point(size=50).encode( - opacity=alt.condition(hover, alt.value(0.8), alt.value(0)), + opacity=when_hover.then(alt.value(0.8)).otherwise(alt.value(0)), ) ) @@ -108,7 +110,7 @@ y='life_expect:Q', text='country:N', color=alt.value('black'), - opacity=alt.condition(hover, alt.value(1), alt.value(0)) + opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)) ).transform_window( rank='rank(life_expect)', sort=[alt.SortField('life_expect', order='descending')], diff --git a/tests/examples_arguments_syntax/scatter_with_histogram.py b/tests/examples_arguments_syntax/scatter_with_histogram.py index dda40dec0d..40cb65c2b6 100644 --- a/tests/examples_arguments_syntax/scatter_with_histogram.py +++ b/tests/examples_arguments_syntax/scatter_with_histogram.py @@ -42,7 +42,7 @@ mag = alt.Chart().mark_bar().encode( x='mbin:N', y="count()", - color=alt.condition(pts, alt.value("black"), alt.value("lightgray")) + color=alt.when(pts).then(alt.value("black")).otherwise(alt.value("lightgray")) ).properties( width=300, height=300 diff --git a/tests/examples_arguments_syntax/scatter_with_layered_histogram.py b/tests/examples_arguments_syntax/scatter_with_layered_histogram.py index 2268b055ce..087d9b405f 100644 --- a/tests/examples_arguments_syntax/scatter_with_layered_histogram.py +++ b/tests/examples_arguments_syntax/scatter_with_layered_histogram.py @@ -30,7 +30,11 @@ color_scale = alt.Scale(domain=['M', 'F'], range=['#1FC3AA', '#8624F5']) - +color = ( + alt.when(selector) + .then(alt.Color("gender:N", scale=color_scale)) + .otherwise(alt.value("lightgray")) +) base = alt.Chart(source).properties( width=250, height=250 @@ -39,11 +43,7 @@ points = base.mark_point(filled=True, size=200).encode( x=alt.X('mean(height):Q', scale=alt.Scale(domain=[0,84])), y=alt.Y('mean(weight):Q', scale=alt.Scale(domain=[0,250])), - color=alt.condition( - selector, - 'gender:N', - alt.value('lightgray'), - scale=color_scale), + color=color, ) hists = base.mark_bar(opacity=0.5, thickness=100).encode( diff --git a/tests/examples_arguments_syntax/scatter_with_minimap.py b/tests/examples_arguments_syntax/scatter_with_minimap.py index a18a599cd4..df8a9fd44d 100644 --- a/tests/examples_arguments_syntax/scatter_with_minimap.py +++ b/tests/examples_arguments_syntax/scatter_with_minimap.py @@ -21,7 +21,7 @@ .encode( x="date:T", y="temp_max:Q", - color=alt.condition(zoom, "weather", alt.value("lightgray")), + color=alt.when(zoom).then("weather").otherwise(alt.value("lightgray")), ) .properties( width=200, diff --git a/tests/examples_arguments_syntax/seattle_weather_interactive.py b/tests/examples_arguments_syntax/seattle_weather_interactive.py index 798cc4780e..63e93d0110 100644 --- a/tests/examples_arguments_syntax/seattle_weather_interactive.py +++ b/tests/examples_arguments_syntax/seattle_weather_interactive.py @@ -28,7 +28,7 @@ title='Maximum Daily Temperature (C)', scale=alt.Scale(domain=[-5, 40]) ), - color=alt.condition(brush, color, alt.value('lightgray')), + color=alt.when(brush).then(color).otherwise(alt.value("lightgray")), size=alt.Size('precipitation:Q', scale=alt.Scale(range=[5, 200])) ).properties( width=550, @@ -43,7 +43,7 @@ bars = alt.Chart().mark_bar().encode( x='count()', y='weather:N', - color=alt.condition(click, color, alt.value('lightgray')), + color=alt.when(click).then(color).otherwise(alt.value("lightgray")), ).transform_filter( brush ).properties( diff --git a/tests/examples_arguments_syntax/select_detail.py b/tests/examples_arguments_syntax/select_detail.py index 500668c4f3..9165e727f7 100644 --- a/tests/examples_arguments_syntax/select_detail.py +++ b/tests/examples_arguments_syntax/select_detail.py @@ -42,6 +42,11 @@ # Data is prepared, now make a chart selector = alt.selection_point(fields=['id']) +color = ( + alt.when(selector) + .then(alt.Color("id:O", legend=None)) + .otherwise(alt.value("lightgray")) +) base = alt.Chart(data).properties( width=250, @@ -51,7 +56,7 @@ points = base.mark_point(filled=True, size=200).encode( x='mean(x)', y='mean(y)', - color=alt.condition(selector, 'id:O', alt.value('lightgray'), legend=None), + color=color, ) line = base.mark_line().encode( diff --git a/tests/examples_arguments_syntax/selection_histogram.py b/tests/examples_arguments_syntax/selection_histogram.py index dc0ccab8ba..155b9fc686 100644 --- a/tests/examples_arguments_syntax/selection_histogram.py +++ b/tests/examples_arguments_syntax/selection_histogram.py @@ -16,7 +16,7 @@ points = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, 'Origin:N', alt.value('lightgray')) + color=alt.when(brush).then("Origin:N").otherwise(alt.value("lightgray")) ).add_params( brush ) diff --git a/tests/examples_arguments_syntax/selection_layer_bar_month.py b/tests/examples_arguments_syntax/selection_layer_bar_month.py index 43f4e97d25..e979147653 100644 --- a/tests/examples_arguments_syntax/selection_layer_bar_month.py +++ b/tests/examples_arguments_syntax/selection_layer_bar_month.py @@ -15,7 +15,7 @@ bars = alt.Chart().mark_bar().encode( x='month(date):O', y='mean(precipitation):Q', - opacity=alt.condition(brush, alt.OpacityValue(1), alt.OpacityValue(0.7)), + opacity = alt.when(brush).then(alt.value(1)).otherwise(alt.value(0.7)), ).add_params( brush ) diff --git a/tests/examples_arguments_syntax/selection_zorder.py b/tests/examples_arguments_syntax/selection_zorder.py index c8e3bd84a1..6f6d7c93d1 100644 --- a/tests/examples_arguments_syntax/selection_zorder.py +++ b/tests/examples_arguments_syntax/selection_zorder.py @@ -16,18 +16,19 @@ cars = data.cars.url hover = alt.selection_point(on='pointerover', nearest=True, empty=False) +when_hover = alt.when(hover) chart = alt.Chart(cars, title='Selection obscured by other points').mark_circle(opacity=1).encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(hover, alt.value('coral'), alt.value('lightgray')), - size=alt.condition(hover, alt.value(300), alt.value(30)) + color=when_hover.then(alt.value("coral")).otherwise(alt.value("lightgray")), + size=when_hover.then(alt.value(300)).otherwise(alt.value(30)) ).add_params( hover ) chart | chart.encode( - order=alt.condition(hover, alt.value(1), alt.value(0)) + order=when_hover.then(alt.value(1)).otherwise(alt.value(0)) ).properties( title='Selection brought to front' ) diff --git a/tests/examples_arguments_syntax/slider_cutoff.py b/tests/examples_arguments_syntax/slider_cutoff.py index 19db774939..786268aeb7 100644 --- a/tests/examples_arguments_syntax/slider_cutoff.py +++ b/tests/examples_arguments_syntax/slider_cutoff.py @@ -17,14 +17,12 @@ slider = alt.binding_range(min=0, max=100, step=1) cutoff = alt.param(bind=slider, value=50) +predicate = alt.datum.xval < cutoff alt.Chart(df).mark_point().encode( x='xval', y='yval', - color=alt.condition( - alt.datum.xval < cutoff, - alt.value('red'), alt.value('blue') - ) + color=alt.when(predicate).then(alt.value("red")).otherwise(alt.value("blue")), ).add_params( cutoff ) \ No newline at end of file diff --git a/tests/examples_arguments_syntax/us_employment.py b/tests/examples_arguments_syntax/us_employment.py index 51f56998f4..2b084290ec 100644 --- a/tests/examples_arguments_syntax/us_employment.py +++ b/tests/examples_arguments_syntax/us_employment.py @@ -21,6 +21,7 @@ "president": "Obama" } ]) +predicate = alt.datum.nonfarm_change > 0 bars = alt.Chart( source, @@ -28,11 +29,7 @@ ).mark_bar().encode( x=alt.X("month:T", title=""), y=alt.Y("nonfarm_change:Q", title="Change in non-farm employment (in thousands)"), - color=alt.condition( - alt.datum.nonfarm_change > 0, - alt.value("steelblue"), - alt.value("orange") - ) + color=alt.when(predicate).then(alt.value("steelblue")).otherwise(alt.value("orange")), ) rule = alt.Chart(presidents).mark_rule( diff --git a/tests/examples_arguments_syntax/us_state_capitals.py b/tests/examples_arguments_syntax/us_state_capitals.py index ad83b8a236..7598dd54c0 100644 --- a/tests/examples_arguments_syntax/us_state_capitals.py +++ b/tests/examples_arguments_syntax/us_state_capitals.py @@ -32,12 +32,12 @@ text = base.mark_text(dy=-5, align='right').encode( alt.Text('city', type='nominal'), - opacity=alt.condition(~hover, alt.value(0), alt.value(1)) + opacity=alt.when(~hover).then(alt.value(0)).otherwise(alt.value(1)) ) points = base.mark_point().encode( color=alt.value('black'), - size=alt.condition(~hover, alt.value(30), alt.value(100)) + size=alt.when(~hover).then(alt.value(30)).otherwise(alt.value(100)) ).add_params(hover) background + points + text diff --git a/tests/examples_arguments_syntax/waterfall_chart.py b/tests/examples_arguments_syntax/waterfall_chart.py index 50f8718f48..bc01e04d46 100644 --- a/tests/examples_arguments_syntax/waterfall_chart.py +++ b/tests/examples_arguments_syntax/waterfall_chart.py @@ -27,36 +27,43 @@ ] source = pd.DataFrame(data) +# Define frequently referenced fields +amount = alt.datum.amount +label = alt.datum.label +window_lead_label = alt.datum.window_lead_label +window_sum_amount = alt.datum.window_sum_amount + +# Define frequently referenced/long expressions +calc_prev_sum = alt.expr.if_(label == "End", 0, window_sum_amount - amount) +calc_amount = alt.expr.if_(label == "End", window_sum_amount, amount) +calc_text_amount = ( + alt.expr.if_((label != "Begin") & (label != "End") & calc_amount > 0, "+", "") + + calc_amount +) + # The "base_chart" defines the transform_window, transform_calculate, and X axis base_chart = alt.Chart(source).transform_window( window_sum_amount="sum(amount)", window_lead_label="lead(label)", ).transform_calculate( - calc_lead="datum.window_lead_label === null ? datum.label : datum.window_lead_label", - calc_prev_sum="datum.label === 'End' ? 0 : datum.window_sum_amount - datum.amount", - calc_amount="datum.label === 'End' ? datum.window_sum_amount : datum.amount", - calc_text_amount="(datum.label !== 'Begin' && datum.label !== 'End' && datum.calc_amount > 0 ? '+' : '') + datum.calc_amount", - calc_center="(datum.window_sum_amount + datum.calc_prev_sum) / 2", - calc_sum_dec="datum.window_sum_amount < datum.calc_prev_sum ? datum.window_sum_amount : ''", - calc_sum_inc="datum.window_sum_amount > datum.calc_prev_sum ? datum.window_sum_amount : ''", + calc_lead=alt.expr.if_((window_lead_label == None), label, window_lead_label), + calc_prev_sum=calc_prev_sum, + calc_amount=calc_amount, + calc_text_amount=calc_text_amount, + calc_center=(window_sum_amount + calc_prev_sum) / 2, + calc_sum_dec=alt.expr.if_(window_sum_amount < calc_prev_sum, window_sum_amount, ""), + calc_sum_inc=alt.expr.if_(window_sum_amount > calc_prev_sum, window_sum_amount, ""), ).encode( - x=alt.X( - "label:O", - axis=alt.Axis(title="Months", labelAngle=0), - sort=None, - ) + x=alt.X("label:O", axis=alt.Axis(title="Months", labelAngle=0), sort=None) ) -# alt.condition does not support multiple if else conditions which is why -# we use a dictionary instead. See https://stackoverflow.com/a/66109641 -# for more information -color_coding = { - "condition": [ - {"test": "datum.label === 'Begin' || datum.label === 'End'", "value": "#878d96"}, - {"test": "datum.calc_amount < 0", "value": "#24a148"}, - ], - "value": "#fa4d56", -} +color_coding = ( + alt.when((label == "Begin") | (label == "End")) + .then(alt.value("#878d96")) + .when(calc_amount < 0) + .then(alt.value("#24a148")) + .otherwise(alt.value("#fa4d56")) +) bar = base_chart.mark_bar(size=45).encode( y=alt.Y("calc_prev_sum:Q", title="Amount"), @@ -65,28 +72,19 @@ ) # The "rule" chart is for the horizontal lines that connect the bars -rule = base_chart.mark_rule( - xOffset=-22.5, - x2Offset=22.5, -).encode( +rule = base_chart.mark_rule(xOffset=-22.5, x2Offset=22.5).encode( y="window_sum_amount:Q", x2="calc_lead", ) # Add values as text -text_pos_values_top_of_bar = base_chart.mark_text( - baseline="bottom", - dy=-4 -).encode( +text_pos_values_top_of_bar = base_chart.mark_text(baseline="bottom", dy=-4).encode( text=alt.Text("calc_sum_inc:N"), - y="calc_sum_inc:Q" + y="calc_sum_inc:Q", ) -text_neg_values_bot_of_bar = base_chart.mark_text( - baseline="top", - dy=4 -).encode( +text_neg_values_bot_of_bar = base_chart.mark_text(baseline="top", dy=4).encode( text=alt.Text("calc_sum_dec:N"), - y="calc_sum_dec:Q" + y="calc_sum_dec:Q", ) text_bar_values_mid_of_bar = base_chart.mark_text(baseline="middle").encode( text=alt.Text("calc_text_amount:N"), diff --git a/tests/examples_methods_syntax/candlestick_chart.py b/tests/examples_methods_syntax/candlestick_chart.py index 47e713abb5..c001f7ddf5 100644 --- a/tests/examples_methods_syntax/candlestick_chart.py +++ b/tests/examples_methods_syntax/candlestick_chart.py @@ -12,12 +12,11 @@ source = data.ohlc() -open_close_color = alt.condition( - "datum.open <= datum.close", - alt.value("#06982d"), - alt.value("#ae1325") +open_close_color = ( + alt.when("datum.open <= datum.close") + .then(alt.value("#06982d")) + .otherwise(alt.value("#ae1325")) ) - base = alt.Chart(source).encode( alt.X('date:T') .axis(format='%m/%d', labelAngle=-45) diff --git a/tests/examples_methods_syntax/interactive_column_selection.py b/tests/examples_methods_syntax/interactive_column_selection.py index a74fba6091..d202f433d3 100644 --- a/tests/examples_methods_syntax/interactive_column_selection.py +++ b/tests/examples_methods_syntax/interactive_column_selection.py @@ -37,7 +37,7 @@ alt.X('level_0').title(None), alt.Y('level_1').title(None), alt.Color('correlation').scale(domain=[-1, 1], scheme='blueorange'), - opacity=alt.condition(select_x & select_y, alt.value(1), alt.value(0.4)) + opacity=alt.when(select_x, select_y).then(alt.value(1)).otherwise(alt.value(0.4)), ).add_params( select_x, select_y ) diff --git a/tests/examples_methods_syntax/interactive_cross_highlight.py b/tests/examples_methods_syntax/interactive_cross_highlight.py index 860a385c29..97dccb3148 100644 --- a/tests/examples_methods_syntax/interactive_cross_highlight.py +++ b/tests/examples_methods_syntax/interactive_cross_highlight.py @@ -29,7 +29,7 @@ bar = alt.Chart(source, width=550, height=200).mark_bar().encode( x='Major_Genre:N', y='count()', - color=alt.condition(pts, alt.ColorValue("steelblue"), alt.ColorValue("grey")) + color=alt.when(pts).then(alt.ColorValue("steelblue")).otherwise(alt.ColorValue("grey")) ).add_params(pts) alt.vconcat( diff --git a/tests/examples_methods_syntax/interactive_legend.py b/tests/examples_methods_syntax/interactive_legend.py index 80c47cf111..e6a6e36f71 100644 --- a/tests/examples_methods_syntax/interactive_legend.py +++ b/tests/examples_methods_syntax/interactive_legend.py @@ -17,7 +17,7 @@ alt.X('yearmonth(date):T').axis(domain=False, format='%Y', tickSize=0), alt.Y('sum(count):Q').stack('center').axis(None), alt.Color('series:N').scale(scheme='category20b'), - opacity=alt.condition(selection, alt.value(1), alt.value(0.2)) + opacity=alt.when(selection).then(alt.value(1)).otherwise(alt.value(0.2)) ).add_params( selection ) diff --git a/tests/examples_methods_syntax/interval_selection_map_quakes.py b/tests/examples_methods_syntax/interval_selection_map_quakes.py index b45afe8da6..f4e89ad65c 100644 --- a/tests/examples_methods_syntax/interval_selection_map_quakes.py +++ b/tests/examples_methods_syntax/interval_selection_map_quakes.py @@ -38,7 +38,7 @@ ).mark_circle(opacity=0.35, tooltip=True).encode( longitude="lon:Q", latitude="lat:Q", - color=alt.condition(brush, alt.value("goldenrod"), alt.value("steelblue")), + color=alt.when(brush).then(alt.value("goldenrod")).otherwise(alt.value("steelblue")), size=alt.Size("mag:Q").scale(type="pow", range=[1, 1000], domain=[0, 7], exponent=4), ).add_params(brush) diff --git a/tests/examples_methods_syntax/lasagna_plot.py b/tests/examples_methods_syntax/lasagna_plot.py index 0da7c44fd6..31ab3ee40f 100644 --- a/tests/examples_methods_syntax/lasagna_plot.py +++ b/tests/examples_methods_syntax/lasagna_plot.py @@ -8,10 +8,10 @@ source = data.stocks() -color_condition = alt.condition( - "month(datum.value) == 1 && date(datum.value) == 1", - alt.value("black"), - alt.value(None), +color_condition = ( + alt.when(alt.expr.month("datum.value") == 1, alt.expr.date("datum.value") == 1) + .then(alt.value("black")) + .otherwise(alt.value(None)) ) alt.Chart(source, width=300, height=100).transform_filter( diff --git a/tests/examples_methods_syntax/layered_heatmap_text.py b/tests/examples_methods_syntax/layered_heatmap_text.py index 7a61c08cbe..ba56f8539e 100644 --- a/tests/examples_methods_syntax/layered_heatmap_text.py +++ b/tests/examples_methods_syntax/layered_heatmap_text.py @@ -27,14 +27,15 @@ .title("Mean of Horsepower") ) +color = ( + alt.when(alt.datum.mean_horsepower > 150) + .then(alt.value("black")) + .otherwise(alt.value("white")) +) + # Configure text text = base.mark_text(baseline='middle').encode( - alt.Text('mean_horsepower:Q', format=".0f"), - color=alt.condition( - alt.datum.mean_horsepower > 150, - alt.value('black'), - alt.value('white') - ) + alt.Text('mean_horsepower:Q', format=".0f"), color=color ) # Draw the chart diff --git a/tests/examples_methods_syntax/multiline_highlight.py b/tests/examples_methods_syntax/multiline_highlight.py index c23bd03725..bbc7634e85 100644 --- a/tests/examples_methods_syntax/multiline_highlight.py +++ b/tests/examples_methods_syntax/multiline_highlight.py @@ -29,7 +29,7 @@ ) lines = base.mark_line().encode( - size=alt.condition(~highlight, alt.value(1), alt.value(3)) + size=alt.when(~highlight).then(alt.value(1)).otherwise(alt.value(3)) ) points + lines diff --git a/tests/examples_methods_syntax/multiline_tooltip.py b/tests/examples_methods_syntax/multiline_tooltip.py index 12ac92bf0d..d2bd7ff8f5 100644 --- a/tests/examples_methods_syntax/multiline_tooltip.py +++ b/tests/examples_methods_syntax/multiline_tooltip.py @@ -41,15 +41,16 @@ ).add_params( nearest ) +when_near = alt.when(nearest) # Draw points on the line, and highlight based on selection points = line.mark_point().encode( - opacity=alt.condition(nearest, alt.value(1), alt.value(0)) + opacity=when_near.then(alt.value(1)).otherwise(alt.value(0)) ) # Draw text labels near the points, and highlight based on selection text = line.mark_text(align="left", dx=5, dy=-5).encode( - text=alt.condition(nearest, "y:Q", alt.value(" ")) + text=when_near.then("y:Q").otherwise(alt.value(" ")) ) # Draw a rule at the location of the selection diff --git a/tests/examples_methods_syntax/multiline_tooltip_standard.py b/tests/examples_methods_syntax/multiline_tooltip_standard.py index 990aa20150..bbab79d46a 100644 --- a/tests/examples_methods_syntax/multiline_tooltip_standard.py +++ b/tests/examples_methods_syntax/multiline_tooltip_standard.py @@ -28,10 +28,11 @@ y="y:Q", color="category:N" ) +when_near = alt.when(nearest) # Draw points on the line, and highlight based on selection points = line.mark_point().encode( - opacity=alt.condition(nearest, alt.value(1), alt.value(0)) + opacity=when_near.then(alt.value(1)).otherwise(alt.value(0)) ) # Draw a rule at the location of the selection @@ -41,7 +42,7 @@ groupby=["x"] ).mark_rule(color="gray").encode( x="x:Q", - opacity=alt.condition(nearest, alt.value(0.3), alt.value(0)), + opacity=when_near.then(alt.value(0.3)).otherwise(alt.value(0)), tooltip=[alt.Tooltip(c, type="quantitative") for c in columns], ).add_params(nearest) diff --git a/tests/examples_methods_syntax/multiple_interactions.py b/tests/examples_methods_syntax/multiple_interactions.py index 0d0ff0ef93..cab6141488 100644 --- a/tests/examples_methods_syntax/multiple_interactions.py +++ b/tests/examples_methods_syntax/multiple_interactions.py @@ -62,32 +62,32 @@ rating_radio = alt.binding_radio(options=ratings, name="Rating") rating_select = alt.selection_point(fields=['MPAA_Rating'], bind=rating_radio) -rating_color_condition = alt.condition( - rating_select, - alt.Color('MPAA_Rating:N').legend(None), - alt.value('lightgray') +rating_color = ( + alt.when(rating_select) + .then(alt.Color("MPAA_Rating:N").legend(None)) + .otherwise(alt.value("lightgray")) ) highlight_ratings = base.add_params( rating_select ).encode( - color=rating_color_condition + color=rating_color ).properties(title="Radio Button Highlighting") # Boolean selection for format changes input_checkbox = alt.binding_checkbox(name="Big Budget Films ") checkbox_selection = alt.param(bind=input_checkbox) -size_checkbox_condition = alt.condition( - checkbox_selection, - alt.Size('Big_Budget_Film:N').scale(range=[25, 150]), - alt.SizeValue(25) +size_checkbox = ( + alt.when(checkbox_selection) + .then(alt.Size('Big_Budget_Film:N').scale(range=[25, 150])) + .otherwise(alt.value(25)) ) budget_sizing = base.add_params( checkbox_selection ).encode( - size=size_checkbox_condition + size=size_checkbox ).properties(title="Checkbox Formatting") (filter_year | budget_sizing) & (highlight_ratings | filter_genres) diff --git a/tests/examples_methods_syntax/scatter_linked_table.py b/tests/examples_methods_syntax/scatter_linked_table.py index 99979e074b..d2fd3f3175 100644 --- a/tests/examples_methods_syntax/scatter_linked_table.py +++ b/tests/examples_methods_syntax/scatter_linked_table.py @@ -18,7 +18,7 @@ points = alt.Chart(source).mark_point().encode( x='Horsepower:Q', y='Miles_per_Gallon:Q', - color=alt.condition(brush, alt.value('steelblue'), alt.value('grey')) + color=alt.when(brush).then(alt.value("steelblue")).otherwise(alt.value("grey")) ).add_params(brush) # Base chart for data tables diff --git a/tests/examples_methods_syntax/scatter_point_paths_hover.py b/tests/examples_methods_syntax/scatter_point_paths_hover.py index a6cc747c72..c6a9c5f198 100644 --- a/tests/examples_methods_syntax/scatter_point_paths_hover.py +++ b/tests/examples_methods_syntax/scatter_point_paths_hover.py @@ -53,14 +53,15 @@ "datum.country !== 'North Korea' && datum.country !== 'South Korea'" ) +search_matches = alt.expr.test(alt.expr.regexp(search_box, "i"), alt.datum.country) +opacity = ( + alt.when(hover_point_opacity, search_matches) + .then(alt.value(0.8)) + .otherwise(alt.value(0.1)) +) # Points that are always visible (filtered by slider and search) visible_points = base.mark_circle(size=100).encode( - opacity=alt.condition( - hover_point_opacity - & alt.expr.test(alt.expr.regexp(search_box, 'i'), alt.datum.country), - alt.value(0.8), - alt.value(0.1) - ) + opacity=opacity ).transform_filter( x_select ).add_params( @@ -69,17 +70,18 @@ x_select ) +when_hover = alt.when(hover) hover_line = alt.layer( # Line layer base.mark_trail().encode( alt.Order('year:Q').sort('ascending'), alt.Size('year:Q').scale(domain=[1955, 2005], range=[1, 12]).legend(None), - opacity=alt.condition(hover, alt.value(0.3), alt.value(0)), + opacity=when_hover.then(alt.value(0.3)).otherwise(alt.value(0)), color=alt.value('#222222') ), # Point layer base.mark_point(size=50).encode( - opacity=alt.condition(hover, alt.value(0.8), alt.value(0)), + opacity=when_hover.then(alt.value(0.8)).otherwise(alt.value(0)), ) ) @@ -101,7 +103,7 @@ y='life_expect:Q', text='country:N', color=alt.value('black'), - opacity=alt.condition(hover, alt.value(1), alt.value(0)) + opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)) ).transform_window( rank='rank(life_expect)', sort=[alt.SortField('life_expect', order='descending')], diff --git a/tests/examples_methods_syntax/scatter_with_layered_histogram.py b/tests/examples_methods_syntax/scatter_with_layered_histogram.py index 2cec759022..ce928f338e 100644 --- a/tests/examples_methods_syntax/scatter_with_layered_histogram.py +++ b/tests/examples_methods_syntax/scatter_with_layered_histogram.py @@ -30,7 +30,11 @@ color_scale = alt.Scale(domain=['M', 'F'], range=['#1FC3AA', '#8624F5']) - +color = ( + alt.when(selector) + .then(alt.Color("gender:N").scale(color_scale)) + .otherwise(alt.value("lightgray")) +) base = alt.Chart(source).properties( width=250, height=250 @@ -39,11 +43,7 @@ points = base.mark_point(filled=True, size=200).encode( alt.X('mean(height):Q').scale(domain=[0,84]), alt.Y('mean(weight):Q').scale(domain=[0,250]), - color=alt.condition( - selector, - 'gender:N', - alt.value('lightgray'), - scale=color_scale), + color=color, ) hists = base.mark_bar(opacity=0.5, thickness=100).encode( diff --git a/tests/examples_methods_syntax/scatter_with_minimap.py b/tests/examples_methods_syntax/scatter_with_minimap.py index 0ad0c634c8..9faafa720b 100644 --- a/tests/examples_methods_syntax/scatter_with_minimap.py +++ b/tests/examples_methods_syntax/scatter_with_minimap.py @@ -21,7 +21,7 @@ .encode( x="date:T", y="temp_max:Q", - color=alt.condition(zoom, "weather", alt.value("lightgray")), + color=alt.when(zoom).then("weather").otherwise(alt.value("lightgray")), ) .properties( width=200, diff --git a/tests/examples_methods_syntax/seattle_weather_interactive.py b/tests/examples_methods_syntax/seattle_weather_interactive.py index 8c59a83d9f..83c7f3e6b8 100644 --- a/tests/examples_methods_syntax/seattle_weather_interactive.py +++ b/tests/examples_methods_syntax/seattle_weather_interactive.py @@ -29,7 +29,7 @@ .title('Maximum Daily Temperature (C)') .scale(domain=[-5, 40]), alt.Size('precipitation:Q').scale(range=[5, 200]), - color=alt.condition(brush, color, alt.value('lightgray')), + color=alt.when(brush).then(color).otherwise(alt.value("lightgray")), ).properties( width=550, height=300 @@ -43,7 +43,7 @@ bars = alt.Chart().mark_bar().encode( x='count()', y='weather:N', - color=alt.condition(click, color, alt.value('lightgray')), + color=alt.when(click).then(color).otherwise(alt.value("lightgray")), ).transform_filter( brush ).properties( diff --git a/tests/examples_methods_syntax/select_detail.py b/tests/examples_methods_syntax/select_detail.py index 58bdb9dfdc..10140bae83 100644 --- a/tests/examples_methods_syntax/select_detail.py +++ b/tests/examples_methods_syntax/select_detail.py @@ -42,6 +42,11 @@ # Data is prepared, now make a chart selector = alt.selection_point(fields=['id']) +color = ( + alt.when(selector) + .then(alt.Color("id:O").legend(None)) + .otherwise(alt.value("lightgray")) +) base = alt.Chart(data).properties( width=250, @@ -51,7 +56,7 @@ points = base.mark_point(filled=True, size=200).encode( x='mean(x)', y='mean(y)', - color=alt.condition(selector, 'id:O', alt.value('lightgray'), legend=None), + color=color, ) line = base.mark_line().encode( diff --git a/tests/examples_methods_syntax/us_employment.py b/tests/examples_methods_syntax/us_employment.py index 775973abf4..24272d44df 100644 --- a/tests/examples_methods_syntax/us_employment.py +++ b/tests/examples_methods_syntax/us_employment.py @@ -21,6 +21,7 @@ "president": "Obama" } ]) +predicate = alt.datum.nonfarm_change > 0 bars = alt.Chart( source, @@ -28,11 +29,7 @@ ).mark_bar().encode( alt.X("month:T").title(""), alt.Y("nonfarm_change:Q").title("Change in non-farm employment (in thousands)"), - color=alt.condition( - alt.datum.nonfarm_change > 0, - alt.value("steelblue"), - alt.value("orange") - ) + color=alt.when(predicate).then(alt.value("steelblue")).otherwise(alt.value("orange")), ) rule = alt.Chart(presidents).mark_rule( diff --git a/tests/examples_methods_syntax/us_state_capitals.py b/tests/examples_methods_syntax/us_state_capitals.py index d9f1390a29..9803cafc59 100644 --- a/tests/examples_methods_syntax/us_state_capitals.py +++ b/tests/examples_methods_syntax/us_state_capitals.py @@ -32,12 +32,12 @@ text = base.mark_text(dy=-5, align='right').encode( alt.Text('city:N'), - opacity=alt.condition(~hover, alt.value(0), alt.value(1)) + opacity=alt.when(~hover).then(alt.value(0)).otherwise(alt.value(1)) ) points = base.mark_point().encode( color=alt.value('black'), - size=alt.condition(~hover, alt.value(30), alt.value(100)) + size=alt.when(~hover).then(alt.value(30)).otherwise(alt.value(100)) ).add_params(hover) background + points + text