From e46a493299eeec14f8448f132baf05021400b053 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:55:36 +0100 Subject: [PATCH 01/38] docs: Replace some inline references No visual change, but makes the markup itself easier to read --- altair/vegalite/v5/api.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index e77d62e00..53da9d25f 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -847,7 +847,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``. @@ -855,6 +855,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:: @@ -927,10 +930,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 -------- @@ -1008,7 +1013,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 @@ -1016,6 +1021,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 -------- @@ -1100,7 +1107,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``. @@ -1108,6 +1115,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:: @@ -1162,7 +1172,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 @@ -1172,11 +1182,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 -------- From a681ec53cb57524f1fd347200df94c88c1d151ef Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:29:23 +0100 Subject: [PATCH 02/38] docs: Update `waterfall_chart.py` example - Replaced `dict` with `when-then-otherwise` - Replaced string expressions with `python` equivalent - Formatting update to avoid horizontal overflow --- .../waterfall_chart.py | 101 +++++++++--------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/tests/examples_arguments_syntax/waterfall_chart.py b/tests/examples_arguments_syntax/waterfall_chart.py index 50f8718f4..835b194e9 100644 --- a/tests/examples_arguments_syntax/waterfall_chart.py +++ b/tests/examples_arguments_syntax/waterfall_chart.py @@ -27,36 +27,47 @@ ] 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 : ''", -).encode( - x=alt.X( - "label:O", - axis=alt.Axis(title="Months", labelAngle=0), - sort=None, +base_chart = ( + alt.Chart(source) + .transform_window(window_sum_amount="sum(amount)", window_lead_label="lead(label)") + .transform_calculate( + 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)) ) -# 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 +76,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"), @@ -94,13 +96,12 @@ color=alt.value("white"), ) -alt.layer( - bar, - rule, - text_pos_values_top_of_bar, - text_neg_values_bot_of_bar, - text_bar_values_mid_of_bar -).properties( - width=800, - height=450 -) \ No newline at end of file +waterfall = ( + bar + + rule + + text_pos_values_top_of_bar + + text_neg_values_bot_of_bar + + text_bar_values_mid_of_bar +).properties(width=800, height=450) + +waterfall \ No newline at end of file From f4540935bc5b3150347669200cd4d1e1a262a379 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:53:07 +0100 Subject: [PATCH 03/38] wip --- altair/vegalite/v5/api.py | 2 +- pyproject.toml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index c256bc73d..d31c73655 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -4902,7 +4902,7 @@ def remove_prop(subchart: ChartType, prop: str) -> ChartType: # or it must be Undefined or identical to proceed. output_dict[prop] = chart[prop] else: - msg = f"There are inconsistent values {values} for {prop}" + msg = f"There are inconsistent values {values} for {prop}" # pyright: ignore[reportPossiblyUnboundVariable] raise ValueError(msg) subcharts = [remove_prop(c, prop) for c in subcharts] diff --git a/pyproject.toml b/pyproject.toml index 4c85070a1..426d8f188 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -436,3 +436,10 @@ extraPaths=["./tools"] pythonPlatform="All" pythonVersion="3.8" reportUnusedExpression="none" +include=[ + "./altair/**/*.py", + ".doc/*.py", + "./sphinxext/**/*.py", + "./tests/**/*.py", + "./tools/**/*.py", +] \ No newline at end of file From 729b7deef7e963e8e56bec4ad79712cd0c871e3c Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:48:02 +0100 Subject: [PATCH 04/38] docs: Use `when` in `expressions.rst` --- doc/user_guide/interactions/expressions.rst | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/doc/user_guide/interactions/expressions.rst b/doc/user_guide/interactions/expressions.rst index a73751ef4..a4e9440ab 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 From 1bc65ce5651b84f7181a6515eafbcbcaab2197ab Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:44:00 +0100 Subject: [PATCH 05/38] docs: Use `when` in `bindings_widgets.rst` --- .../interactions/bindings_widgets.rst | 40 ++++++------------- doc/user_guide/interactions/parameters.rst | 2 + 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/doc/user_guide/interactions/bindings_widgets.rst b/doc/user_guide/interactions/bindings_widgets.rst index dc62a6e11..6382e9b1f 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/parameters.rst b/doc/user_guide/interactions/parameters.rst index 1dce8c116..2f82c72f6 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -146,6 +146,8 @@ 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 & Filters ~~~~~~~~~~~~~~~~~~~~ From f9277fa91dc1bcdc19afa8240df6b4abb4112bcd Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:19:21 +0100 Subject: [PATCH 06/38] docs: Use `when` in `exploring-weather.rst` --- doc/case_studies/exploring-weather.rst | 48 +++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/doc/case_studies/exploring-weather.rst b/doc/case_studies/exploring-weather.rst index bc9776787..058085faa 100644 --- a/doc/case_studies/exploring-weather.rst +++ b/doc/case_studies/exploring-weather.rst @@ -226,33 +226,33 @@ 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]) - ).transform_calculate( - "temp_range", "datum.temp_max - datum.temp_min" - ).properties( - width=600, - height=400 - ).add_params( - brush + color = ( + alt.when(brush) + .then(alt.Color("weather:N").scale(scale)) + .otherwise(alt.value("lightgray")) ) - bars = alt.Chart().mark_bar().encode( - x='count()', - y='weather:N', - color=alt.Color('weather:N').scale(scale), - ).transform_calculate( - "temp_range", "datum.temp_max - datum.temp_min" - ).transform_filter( - brush - ).properties( - width=600 + 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=color, + size=alt.Size("precipitation:Q").scale(range=[1, 200]), + ) + .transform_calculate("temp_range", "datum.temp_max - datum.temp_min") + .properties(width=600, height=400) + .add_params(brush) + ) + bars = ( + alt.Chart() + .mark_bar() + .encode(x="count()", y="weather:N", color=alt.Color("weather:N").scale(scale)) + .transform_calculate("temp_range", "datum.temp_max - datum.temp_min") + .transform_filter(brush) + .properties(width=600) ) - alt.vconcat(points, bars, data=df) This chart, containing concatenations, data transformations, selections, and From 961eb130fe8629295c22ee60d6a969153278a786 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:23:59 +0100 Subject: [PATCH 07/38] docs: Use `when` in `filter.rst` --- doc/user_guide/transform/filter.rst | 36 ++++++++++++----------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/doc/user_guide/transform/filter.rst b/doc/user_guide/transform/filter.rst index 3fca3f196..73f43ae16 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 - ).transform_filter( - selection + top = ( + alt.Chart() + .mark_line() + .encode(x="age:O", y="sum(people):Q", color="year:O") + .properties(width=600, height=200) + .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 - ).add_params( - selection + color = ( + alt.when(selection).then(alt.value("steelblue")).otherwise(alt.value("lightgray")) ) - - alt.vconcat( - top, bottom, - data=pop + bottom = ( + alt.Chart() + .mark_bar() + .encode(x="year:O", y="sum(people):Q", color=color) + .properties(width=600, height=100) + .add_params(selection) ) + alt.vconcat(top, bottom, data=pop) Logical Operands ^^^^^^^^^^^^^^^^ From d886fbecb05965da69f8f3a14286f2884ca5fd2d Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:28:37 +0100 Subject: [PATCH 08/38] docs: Use `when` in `pivot.rst` --- doc/user_guide/transform/pivot.rst | 44 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/doc/user_guide/transform/pivot.rst b/doc/user_guide/transform/pivot.rst index eb3746c73..24258cb82 100644 --- a/doc/user_guide/transform/pivot.rst +++ b/doc/user_guide/transform/pivot.rst @@ -43,27 +43,29 @@ values on multiple lines: .. altair-plot:: - 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' - ) - - 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)), - tooltip=[alt.Tooltip(c, type='quantitative') for c in columns] - ).add_params(selection) - - lines + points + rule + 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' + ) + + 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.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 Transform Options From 9ca591eb13d4e7353b36182103adc8d0803b883e Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:44:14 +0100 Subject: [PATCH 09/38] docs: Use `when` in `compound_charts.rst` --- doc/user_guide/compound_charts.rst | 34 +++++++++++++----------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/doc/user_guide/compound_charts.rst b/doc/user_guide/compound_charts.rst index 503add798..171e83f28 100644 --- a/doc/user_guide/compound_charts.rst +++ b/doc/user_guide/compound_charts.rst @@ -364,28 +364,24 @@ layered chart with a hover selection: .. altair-plot:: hover = alt.selection_point(on='pointerover', nearest=True, empty=False) - - base = alt.Chart(iris).encode( - x='petalLength:Q', - y='petalWidth:Q', - color=alt.condition(hover, 'species:N', alt.value('lightgray')) - ).properties( - width=180, - height=180, + when_hover = alt.when(hover) + + base = ( + alt.Chart(iris) + .encode( + x="petalLength:Q", + y="petalWidth:Q", + 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)) - ) - - alt.layer(points, text).facet( - 'species:N', + text="species:N", + opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)), ) + + (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 From fe5f8e54025c97d3e447e007179a4225f9b30cf9 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:50:57 +0100 Subject: [PATCH 10/38] docs: Use `when` in `times_and_dates.rst` --- doc/user_guide/times_and_dates.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/user_guide/times_and_dates.rst b/doc/user_guide/times_and_dates.rst index a8cd47ab3..98ad9390c 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": From b0893e255c698d370103c60ec508c437a9917f50 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:54:43 +0100 Subject: [PATCH 11/38] docs: Use `when` in `line.rst` --- doc/user_guide/marks/line.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/marks/line.rst b/doc/user_guide/marks/line.rst index 13f638f25..feda5bbf5 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 From 008ff8d1acc56e78d8d0fbe5f9fc5035060dc2ee Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 18:00:05 +0100 Subject: [PATCH 12/38] docs: Use `when` in `text.rst` --- doc/user_guide/marks/text.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/user_guide/marks/text.rst b/doc/user_guide/marks/text.rst index 4bae2f8b5..35d363fce 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 From 4fe1e9c72b5221fe353c65509f2fc0663289d9ed Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 18:11:00 +0100 Subject: [PATCH 13/38] docs: Use `when` in `geoshape.rst` --- doc/user_guide/marks/geoshape.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/user_guide/marks/geoshape.rst b/doc/user_guide/marks/geoshape.rst index 4db48f98c..4c612ca61 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), From 62695331ead3e1c805d2a6d43ad77e906f76c3a5 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 18:13:30 +0100 Subject: [PATCH 14/38] docs: Use `when` in `README.md` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e14e8826..6134975c6 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 ) From f08d96feaf1e9e293906adbb3265fcdb032ce0da Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 4 Sep 2024 19:28:46 +0100 Subject: [PATCH 15/38] docs: Use `when` in `jupyter_chart.rst` --- doc/user_guide/interactions/jupyter_chart.rst | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/doc/user_guide/interactions/jupyter_chart.rst b/doc/user_guide/interactions/jupyter_chart.rst index 88982c06b..a4ad028d1 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()) From 1d6be1665348e6f31e25b23e89659fc2fe245d5f Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:48:05 +0100 Subject: [PATCH 16/38] docs(DRAFT): Use `when` in `parameters.rst` First draft version. Unlike the other commits, this has to introduce the concept - so will require more scrutiny. https://github.com/vega/altair/pull/3544#issuecomment-2329600439 --- doc/user_guide/interactions/parameters.rst | 71 ++++++++++++++-------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 2f82c72f6..17bd47565 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -156,31 +156,45 @@ Conditional Encodings 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 +the chart specification. Here, we will use the :func:`when` 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: .. 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')) - ).add_params( - brush - ) + x="Horsepower:Q", + y="Miles_per_Gallon:Q", + color=conditional, + ).add_params(brush) 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(, , )``. - +and the ``alt.value('lightgray')`` specifies that the outside points should be given a constant color value. + +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") + This approach becomes 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 @@ -193,7 +207,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 @@ -220,7 +234,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 @@ -233,15 +247,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))``. +we can change the order in which they are laid out via the following encoding :: + + hover = alt.selection_point(on='pointerover', nearest=True, empty=False) + order = alt.when(hover).then(alt.value(1)).otherwise(alt.value(0)) + You can see an example of this in the :ref:`gallery_selection_zorder` gallery example. Filtering Data ^^^^^^^^^^^^^^ 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, @@ -298,7 +315,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(brush).then("count()").otherwise(alt.value("lightgray")), ).properties( width=300, height=180 @@ -369,10 +386,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( @@ -404,10 +421,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( @@ -464,7 +481,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( @@ -484,3 +501,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 From d9899f56d1dc52a8e7d45ade95e971bc406cb429 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:23:31 +0100 Subject: [PATCH 17/38] docs: Proofread `parameters.rst` - Mostly correcting formatting issues. - Removed some immediately repeated info that followed `when`. - Added a ref to `alt.Chart` --- doc/user_guide/interactions/parameters.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 17bd47565..3f316892f 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -155,11 +155,9 @@ Conditional Encodings ^^^^^^^^^^^^^^^^^^^^^ 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 +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: 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: +a conditional color encoding: .. altair-plot:: @@ -175,17 +173,17 @@ As you can see, the color of the points now changes depending on whether they ar Above we are using the selection parameter ``brush`` as a *predicate* (something that evaluates as `True` or `False`). -This is controlled by our definition ``conditional`` :: +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, +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. The ``when-then-otherwise`` syntax was directly inspired by `polars.when`_, -and is similar to an ``if-else`` statement written in Python :: +and is similar to an ``if-else`` statement written in Python:: # alt.when(brush) if brush: @@ -197,7 +195,7 @@ and is similar to an ``if-else`` statement written in Python :: This approach becomes 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"`` @@ -247,7 +245,7 @@ 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 :: +we can change the order in which they are laid out via the following encoding:: hover = alt.selection_point(on='pointerover', nearest=True, empty=False) order = alt.when(hover).then(alt.value(1)).otherwise(alt.value(0)) From e6a9b9cf0538d0ba6e8e9dd8b645193155e4a7a5 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:38:41 +0100 Subject: [PATCH 18/38] docs: Add callout referencing change https://github.com/vega/altair/pull/3544#issuecomment-2329471941 --- doc/user_guide/interactions/parameters.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 3f316892f..a569fb0c5 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -154,6 +154,11 @@ Conditions & Filters Conditional Encodings ^^^^^^^^^^^^^^^^^^^^^ +.. 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 ``brush`` within the chart specification. Here, we will use the :func:`when` function to create From dfab00c6f2c023011d3804e9fafd2d59bf533a96 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:43:25 +0100 Subject: [PATCH 19/38] docs: Use `when` in all methods syntax examples --- .../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 | 12 +++---- .../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 | 31 +++++++++---------- .../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 +-- 19 files changed, 73 insertions(+), 70 deletions(-) diff --git a/tests/examples_methods_syntax/candlestick_chart.py b/tests/examples_methods_syntax/candlestick_chart.py index 47e713abb..c001f7ddf 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 a74fba609..d202f433d 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 860a385c2..97dccb314 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 80c47cf11..e6a6e36f7 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 b45afe8da..f4e89ad65 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 0da7c44fd..247ced8a3 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( @@ -23,8 +23,8 @@ format="%Y", labelAngle=0, labelOverlap=False, - labelColor=color_condition, - tickColor=color_condition, + labelColor=color_condition, # type: ignore[call-overload] + tickColor=color_condition, # pyright: ignore[reportArgumentType] ), alt.Y("symbol:N").title(None), alt.Color("sum(price)").title("Price") diff --git a/tests/examples_methods_syntax/layered_heatmap_text.py b/tests/examples_methods_syntax/layered_heatmap_text.py index 7a61c08cb..ba56f8539 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 c23bd0372..bbc7634e8 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 12ac92bf0..d2bd7ff8f 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 990aa2015..bbab79d46 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 0d0ff0ef9..cab614148 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 99979e074..d2fd3f317 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 a6cc747c7..713792401 100644 --- a/tests/examples_methods_syntax/scatter_point_paths_hover.py +++ b/tests/examples_methods_syntax/scatter_point_paths_hover.py @@ -53,33 +53,32 @@ "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) - ) - ).transform_filter( - x_select - ).add_params( - hover, - hover_point_opacity, - x_select +visible_points = ( + base.mark_circle(size=100) + .encode(opacity=opacity) + .transform_filter(x_select) + .add_params(hover, hover_point_opacity, 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 +100,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 2cec75902..ce928f338 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 0ad0c634c..9faafa720 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 8c59a83d9..83c7f3e6b 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 58bdb9dfd..10140bae8 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 775973abf..24272d44d 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 d9f1390a2..9803cafc5 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 From ff0bc34f97d86e45d504f1e6f477729a95772ab9 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:06:08 +0100 Subject: [PATCH 20/38] docs: Use `when` in arguments syntax examples (1/2) Covers all the examples that had a *methods* equivalent. Now have 16 more to do, across 12 files --- .../interactive_column_selection.py | 2 +- .../interactive_cross_highlight.py | 2 +- .../interactive_legend.py | 2 +- .../interval_selection_map_quakes.py | 2 +- .../examples_arguments_syntax/lasagna_plot.py | 12 +++---- .../layered_heatmap_text.py | 12 +++---- .../multiline_highlight.py | 2 +- .../multiline_tooltip.py | 5 +-- .../multiline_tooltip_standard.py | 5 +-- .../multiple_interactions.py | 22 ++++++------- .../scatter_linked_table.py | 2 +- .../scatter_point_paths_hover.py | 31 +++++++++---------- .../scatter_with_layered_histogram.py | 12 +++---- .../scatter_with_minimap.py | 2 +- .../seattle_weather_interactive.py | 4 +-- .../select_detail.py | 7 ++++- .../us_employment.py | 7 ++--- .../us_state_capitals.py | 4 +-- 18 files changed, 69 insertions(+), 66 deletions(-) diff --git a/tests/examples_arguments_syntax/interactive_column_selection.py b/tests/examples_arguments_syntax/interactive_column_selection.py index 1c82aad8f..0fa4826aa 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 796dc3110..f2b7e2d2a 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 bd8b14b1a..61e45f44d 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/interval_selection_map_quakes.py b/tests/examples_arguments_syntax/interval_selection_map_quakes.py index 6ab6bed8d..3a2d71c86 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 6f603b8e1..37a9ecd17 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( @@ -23,8 +23,8 @@ format="%Y", labelAngle=0, labelOverlap=False, - labelColor=color_condition, - tickColor=color_condition, + labelColor=color_condition, # type: ignore[arg-type] + tickColor=color_condition, # type: ignore[arg-type] ), title="Time", ), diff --git a/tests/examples_arguments_syntax/layered_heatmap_text.py b/tests/examples_arguments_syntax/layered_heatmap_text.py index dc912ed8b..7dec0fd26 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 5da841516..575c88081 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 12ac92bf0..d2bd7ff8f 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 990aa2015..bbab79d46 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 8fbc4281e..96bfb8fed 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_table.py b/tests/examples_arguments_syntax/scatter_linked_table.py index 93777b751..e17c4dbb0 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 ee755b9e0..fd8f0a8bf 100644 --- a/tests/examples_arguments_syntax/scatter_point_paths_hover.py +++ b/tests/examples_arguments_syntax/scatter_point_paths_hover.py @@ -53,22 +53,21 @@ "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) - ) - ).transform_filter( - x_select - ).add_params( - hover, - hover_point_opacity, - x_select +visible_points = ( + base.mark_circle(size=100) + .encode(opacity=opacity) + .transform_filter(x_select) + .add_params(hover, hover_point_opacity, x_select) ) +when_hover = alt.when(hover) hover_line = alt.layer( # Line layer base.mark_trail().encode( @@ -81,12 +80,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 +107,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_layered_histogram.py b/tests/examples_arguments_syntax/scatter_with_layered_histogram.py index 2268b055c..087d9b405 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 a18a599cd..df8a9fd44 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 798cc4780..63e93d011 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 500668c4f..9165e727f 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/us_employment.py b/tests/examples_arguments_syntax/us_employment.py index 51f56998f..2b084290e 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 ad83b8a23..7598dd54c 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 From 390d59935bf1cf81ce4988fdc6099b9d9a50b790 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:42:03 +0100 Subject: [PATCH 21/38] docs: Use `when` in arguments syntax examples (2/2) --- .../bar_chart_with_highlighted_bar.py | 22 ++++++++++--------- .../bar_chart_with_negatives.py | 19 ++++++++-------- .../candlestick_chart.py | 8 ++++--- .../dot_dash_plot.py | 8 ++++--- .../interactive_brush.py | 2 +- .../interactive_reorder_stacked_bars.py | 2 +- .../scatter_linked_brush.py | 2 +- .../scatter_with_histogram.py | 2 +- .../selection_histogram.py | 2 +- .../selection_layer_bar_month.py | 2 +- .../selection_zorder.py | 7 +++--- .../slider_cutoff.py | 6 ++--- 12 files changed, 44 insertions(+), 38 deletions(-) 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 d277bf9f3..511f44f15 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,15 @@ source = data.wheat() -alt.Chart(source).mark_bar().encode( - 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. - ) -).properties(width=600) +# 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")) + +chart = ( + alt.Chart(source) + .mark_bar() + .encode(x="year:O", y="wheat:Q", color=color) + .properties(width=600) +) +chart \ No newline at end of file diff --git a/tests/examples_arguments_syntax/bar_chart_with_negatives.py b/tests/examples_arguments_syntax/bar_chart_with_negatives.py index 127a16ba4..647b67c76 100644 --- a/tests/examples_arguments_syntax/bar_chart_with_negatives.py +++ b/tests/examples_arguments_syntax/bar_chart_with_negatives.py @@ -9,12 +9,13 @@ source = data.us_employment() -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 - ) -).properties(width=600) +predicate = alt.datum.nonfarm_change > 0 +color = alt.when(predicate).then(alt.value("steelblue")).otherwise(alt.value("orange")) + +chart = ( + alt.Chart(source) + .mark_bar() + .encode(x="month:T", y="nonfarm_change:Q", color=color) + .properties(width=600) +) +chart \ No newline at end of file diff --git a/tests/examples_arguments_syntax/candlestick_chart.py b/tests/examples_arguments_syntax/candlestick_chart.py index 23b338b8e..4dc524782 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 72d73d2e8..64c6ef450 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 2cfd66037..bee087c57 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_reorder_stacked_bars.py b/tests/examples_arguments_syntax/interactive_reorder_stacked_bars.py index 606bc37a1..2fbed1dca 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/scatter_linked_brush.py b/tests/examples_arguments_syntax/scatter_linked_brush.py index adf88d34b..b8548fd02 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_with_histogram.py b/tests/examples_arguments_syntax/scatter_with_histogram.py index dda40dec0..40cb65c2b 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/selection_histogram.py b/tests/examples_arguments_syntax/selection_histogram.py index dc0ccab8b..155b9fc68 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 43f4e97d2..e97914765 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 c8e3bd84a..6f6d7c93d 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 19db77493..786268aeb 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 From 6d6b8a66b30c068ce9cfc5c85b22e923cc1d47d9 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:37:21 +0100 Subject: [PATCH 22/38] chore(typing): Removed fixed ignore comments --- tests/examples_arguments_syntax/lasagna_plot.py | 4 ++-- tests/examples_methods_syntax/lasagna_plot.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/examples_arguments_syntax/lasagna_plot.py b/tests/examples_arguments_syntax/lasagna_plot.py index 37a9ecd17..d3e60ed34 100644 --- a/tests/examples_arguments_syntax/lasagna_plot.py +++ b/tests/examples_arguments_syntax/lasagna_plot.py @@ -23,8 +23,8 @@ format="%Y", labelAngle=0, labelOverlap=False, - labelColor=color_condition, # type: ignore[arg-type] - tickColor=color_condition, # type: ignore[arg-type] + labelColor=color_condition, + tickColor=color_condition, ), title="Time", ), diff --git a/tests/examples_methods_syntax/lasagna_plot.py b/tests/examples_methods_syntax/lasagna_plot.py index 247ced8a3..31ab3ee40 100644 --- a/tests/examples_methods_syntax/lasagna_plot.py +++ b/tests/examples_methods_syntax/lasagna_plot.py @@ -23,8 +23,8 @@ format="%Y", labelAngle=0, labelOverlap=False, - labelColor=color_condition, # type: ignore[call-overload] - tickColor=color_condition, # pyright: ignore[reportArgumentType] + labelColor=color_condition, + tickColor=color_condition, ), alt.Y("symbol:N").title(None), alt.Color("sum(price)").title("Price") From fb42da7de606ec03b8d58773479374492f6e93be Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:29:53 +0100 Subject: [PATCH 23/38] fix: Use `selector` argument in `make_example` All of the charts using this function were silently producing no output. `brush` had been defined globally in an earlier directive https://github.com/vega/altair/pull/3544#discussion_r1764228089 --- doc/user_guide/interactions/parameters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index a569fb0c5..eeaf8d0f8 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -318,7 +318,7 @@ selection: return alt.Chart(cars).mark_rect().encode( x="Cylinders:O", y="Origin:N", - color=alt.when(brush).then("count()").otherwise(alt.value("lightgray")), + color=alt.when(selector).then("count()").otherwise(alt.value("lightgray")), ).properties( width=300, height=180 From 50a520e9314108d572ef8bd6d48f0135151d2c6c Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:13:31 +0100 Subject: [PATCH 24/38] docs: Add new subsection content Not sure what the title should be, but @joelostblom proposed making this a new subsection https://github.com/vega/altair/pull/3544#pullrequestreview-2311368912 --- doc/user_guide/interactions/parameters.rst | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index eeaf8d0f8..5872d105f 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -257,6 +257,52 @@ we can change the order in which they are laid out via the following encoding:: You can see an example of this in the :ref:`gallery_selection_zorder` gallery example. +Untitled More When +^^^^^^^^^^^^^^^^^^ +Simple conditions may be expressed without defining a default: + +.. altair-plot:: + + source = data.cars() + brush = alt.selection_interval() + color = alt.when(brush).then("Origin") + + points = ( + alt.Chart(source) + .mark_point() + .encode(x="Horsepower", y="Miles_per_Gallon", color=color) + .add_params(brush) + ) + points + +Chain calls to express precise queries: + +.. altair-plot:: + + source = data.cars() + color = ( + alt.when(alt.datum.Miles_per_Gallon >= 30, Origin="Europe") + .then(alt.value("crimson")) + .when(alt.datum.Horsepower > 150) + .then(alt.value("goldenrod")) + .otherwise(alt.value("grey")) + ) + + points = ( + alt.Chart(source) + .mark_point() + .encode(x="Horsepower", y="Miles_per_Gallon", color=color) + ) + points + +You can see more in :func:`when` and throughout many gallery examples: + +- :ref:`gallery_dot_dash_plot` +- :ref:`gallery_multiline_tooltip_standard` +- :ref:`gallery_scatter_point_paths_hover` +- :ref:`gallery_waterfall_chart` + + Filtering Data ^^^^^^^^^^^^^^ From df5555cd869c4b4b4b7bf638da08850346110915 Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:21:13 +0100 Subject: [PATCH 25/38] docs: Add link to `interactive_bar_select_highlight.rst` https://altair-viz.github.io/gallery/interactive_bar_select_highlight.html --- doc/user_guide/interactions/parameters.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 5872d105f..421b4b1fe 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -298,6 +298,7 @@ Chain calls to express precise queries: You can see more in :func:`when` and throughout many 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` From e363abdfb2fb1c16a0afaf6338c268f286771e5c Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Thu, 19 Sep 2024 12:13:32 -0700 Subject: [PATCH 26/38] Expand explanation of `when` To be able to fully document the behavior of `when`, I made a few organizational changes: - Split "Conditions" and "Filter" since these are two different concept anyways. - I also renamed the first heading to illustratet that the three big concepts are "Parameter", "Conditions", and "Filters". - Named the main new "when" section "Understanding when()" and included an example of conditional branches in pseudocode early on and a runnable example later. - I also added an additional subheading for "Linking across charts" - Included mention of the use of `empty=False` inside `when` together with a short pseudocode example. - Creating a new section at the end about combining parameters, which contains both the previous section on parameter composition, but also two new subsection on multiple conditions and conditional when branches. - I expanded on the parameter composition examples as well. --- .../interactions/bindings_widgets.rst | 2 +- doc/user_guide/interactions/parameters.rst | 261 +++++++++++++----- 2 files changed, 194 insertions(+), 69 deletions(-) diff --git a/doc/user_guide/interactions/bindings_widgets.rst b/doc/user_guide/interactions/bindings_widgets.rst index 6382e9b1f..9a62307dc 100644 --- a/doc/user_guide/interactions/bindings_widgets.rst +++ b/doc/user_guide/interactions/bindings_widgets.rst @@ -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 :ref:`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. diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 421b4b1fe..7f3acd1b3 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,13 +149,10 @@ 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 & Filters -~~~~~~~~~~~~~~~~~~~~ +.. _conditions: -Conditional Encodings -^^^^^^^^^^^^^^^^^^^^^ +Conditions +~~~~~~~~~~ .. note:: @@ -187,7 +187,10 @@ 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. -The ``when-then-otherwise`` syntax was directly inspired by `polars.when`_, +Understanding :func:`when` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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) @@ -197,8 +200,51 @@ and is similar to an ``if-else`` statement written in Python:: else: # .otherwise(alt.value("lightgray")) color = alt.value("lightgray") - -This approach becomes even more powerful when the selection behavior is + +As a convenience, +simple conditions may be expressed without defining a default: + +.. altair-plot:: + + source = data.cars() + brush = alt.selection_interval() + color = alt.when(brush).then(alt.value('goldenrod')) + + points = ( + alt.Chart(source) + .mark_point() + .encode(x="Horsepower", y="Miles_per_Gallon", color=color) + .add_params(brush) + ) + points + +Multiple conditional branches (``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. +For now, you can use this pseudocode +as an example of what the syntax would look like:: + + alt.when(brush1) + .then(alt.value("goldenrod")) + .when(brush2) + .then(alt.value("crimson")) + .otherwise(alt.value("grey")) + +More advanced usage 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 :class:`Chart` using the same code as above, and horizontally concatenate two versions of this chart: one @@ -251,61 +297,17 @@ 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:: - + hover = alt.selection_point(on='pointerover', nearest=True, empty=False) order = alt.when(hover).then(alt.value(1)).otherwise(alt.value(0)) -You can see an example of this in the :ref:`gallery_selection_zorder` gallery example. - -Untitled More When -^^^^^^^^^^^^^^^^^^ -Simple conditions may be expressed without defining a default: .. altair-plot:: - - source = data.cars() - brush = alt.selection_interval() - color = alt.when(brush).then("Origin") - - points = ( - alt.Chart(source) - .mark_point() - .encode(x="Horsepower", y="Miles_per_Gallon", color=color) - .add_params(brush) - ) - points - -Chain calls to express precise queries: -.. altair-plot:: - - source = data.cars() - color = ( - alt.when(alt.datum.Miles_per_Gallon >= 30, Origin="Europe") - .then(alt.value("crimson")) - .when(alt.datum.Horsepower > 150) - .then(alt.value("goldenrod")) - .otherwise(alt.value("grey")) - ) - - points = ( - alt.Chart(source) - .mark_point() - .encode(x="Horsepower", y="Miles_per_Gallon", color=color) - ) - points - -You can see more in :func:`when` and throughout many 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` -Filtering Data -^^^^^^^^^^^^^^ +Filters +~~~~~~~ Using a selection parameter to filter data works in much the same way as using it within :func:`when`. @@ -397,6 +399,15 @@ 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`, +so that you don't need to redefine the same selection, e.g.:: + + brush = alt.selection() + ... + 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 @@ -497,41 +508,154 @@ 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 :fun:`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 +^^^^^^^^^^^^^^^^^^^^ + +:fun:`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 operands. +These parameter compositions can be used with both filters and conditions in Altair. +In the following example, +only the points that fall within the interval selections of both the scatter plots +will be counted in the bar chart +(so you will need to make a selection in both charts +before the bars shows up). -Returning to our heatmap examples, -we can construct a scenario where there are two people who can make an interval +.. altair-plot:: + + # empty=False ensure that no points are selected before a selection is drawn + brush = alt.selection_interval(empty=False) + brush2 = alt.selection_interval(empty=False) + + points = alt.Chart(cars).mark_point(size=10).encode( + x='Horsepower:Q', + y='Miles_per_Gallon:Q', + color='Origin:N' + ) + + points2 = points.encode( + x='Acceleration:Q', + y='Miles_per_Gallon:Q', + ) + + bars = alt.Chart(cars).mark_bar().encode( + x='count()', + y='Origin:N', + color='Origin:N' + ).transform_filter( + brush & brush2 + ) + + (points.add_params(brush) | points2.add_params(brush2)) & bars + +To illustrate how a more complex parameter composition +can be applied to a conditional encoding, +we can return to our heatmap example. +Let's construct a scenario where there are two people who can make an interval selection in the same chart. The person Alex makes a selection box when the alt-key (macOS: option-key) is selected and Morgan can make a selection box when the shift-key is selected. -We use :class:`BrushConfig` to give the selection box of Morgan a different -style. -Now, we color the rectangles when they fall within Alex's or Morgan's -selection +Now, we color the chart marks when they fall within Alex's or Morgan's +selection, but not both's (note that you need to create both selections before seeing the effect). +Here, we also use We use :class:`BrushConfig` to give the selection box of Morgan a different +style to be able to tell them apart. .. altair-plot:: alex = alt.selection_interval( on="[pointerdown[event.altKey], pointerup] > pointermove", - name='alex' + empty=False, ) morgan = alt.selection_interval( on="[pointerdown[event.shiftKey], pointerup] > pointermove", mark=alt.BrushConfig(fill="#fdbb84", fillOpacity=0.5, stroke="#e34a33"), - name='morgan' + empty=False, ) + either_or_but_not_both = (alex | morgan) & ~(alex & morgan) + alt.Chart(cars).mark_rect().encode( x='Cylinders:O', y='Origin:O', - color=alt.when(alex | morgan).then("count()").otherwise(alt.value("grey")), + color=alt.when(either_or_but_not_both).then("count()").otherwise(alt.value("grey")), ).add_params( alex, morgan ).properties( @@ -541,9 +665,10 @@ selection With these operators, selections can be combined in arbitrary ways: +- ``alex | morgan``: to select the rectangles that fall inside either + Alex's or Morgans' selection. - ``~(alex & morgan)``: to select the rectangles that fall outside Alex's and Morgan's selections. - - ``alex | ~morgan``: to select the rectangles that fall within Alex's selection or outside the selection of Morgan From 0af35df7ff0e043f430c9da3f826ca20928e962e Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:07:56 -0700 Subject: [PATCH 27/38] Fix typo Co-authored-by: Dan Redding <125183946+dangotbanned@users.noreply.github.com> --- doc/user_guide/interactions/parameters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 7f3acd1b3..aa1e0443f 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -513,7 +513,7 @@ Combining Parameters Multiple parameters can be combined in a single chart, either via multiple separate response conditions, -different conditional branches in :fun:`when`, +different conditional branches in :func:`when`, or parameter composition. Multiple conditions From b39dcdfe50e76167dca8a41b15430bf54ba13bf4 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:08:13 -0700 Subject: [PATCH 28/38] Fix typo Co-authored-by: Dan Redding <125183946+dangotbanned@users.noreply.github.com> --- doc/user_guide/interactions/parameters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index aa1e0443f..9ec7f2b02 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -548,7 +548,7 @@ Try holding shift to select multiple points on either hover or click. Conditional branches ^^^^^^^^^^^^^^^^^^^^ -:fun:`when` allows the use of multiple ``then`` (``elif``) 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, From e26b653f26906a8851e9c4778ecc683728497207 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:17:41 -0700 Subject: [PATCH 29/38] Remove empty code block Co-authored-by: Dan Redding <125183946+dangotbanned@users.noreply.github.com> --- doc/user_guide/interactions/parameters.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 9ec7f2b02..c272919e2 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -302,9 +302,6 @@ we can change the order in which they are laid out via the following encoding:: order = alt.when(hover).then(alt.value(1)).otherwise(alt.value(0)) -.. altair-plot:: - - Filters ~~~~~~~ From 355fee9e733a2ea54ca834099e68e6762a155855 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:20:12 -0700 Subject: [PATCH 30/38] Use correct method name Co-authored-by: Dan Redding <125183946+dangotbanned@users.noreply.github.com> --- doc/user_guide/interactions/parameters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index c272919e2..5d5dd0a1a 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -399,7 +399,7 @@ empty selection contains none of the points: The ``empty=False`` argument could instead be set inside :func:`when`, so that you don't need to redefine the same selection, e.g.:: - brush = alt.selection() + brush = alt.selection_interval() ... color=alt.when(brush).then(...) size=alt.when(brush, empty=False).then(...) From c3155f22baace2310dc6fdb923e832a334c46acc Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:10:38 -0700 Subject: [PATCH 31/38] Update param name to "exclusive_or" --- doc/user_guide/interactions/parameters.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 5d5dd0a1a..8bf564015 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -647,12 +647,12 @@ style to be able to tell them apart. empty=False, ) - either_or_but_not_both = (alex | morgan) & ~(alex & morgan) + exlusive_or = (alex | morgan) & ~(alex & morgan) alt.Chart(cars).mark_rect().encode( x='Cylinders:O', y='Origin:O', - color=alt.when(either_or_but_not_both).then("count()").otherwise(alt.value("grey")), + color=alt.when(exlusive_or).then("count()").otherwise(alt.value("grey")), ).add_params( alex, morgan ).properties( From 08e40d822fcadb5381782a0c7eb054c78d927a9a Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:17:28 -0700 Subject: [PATCH 32/38] Improve wording --- doc/user_guide/interactions/parameters.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 8bf564015..54f2bc7dd 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -201,8 +201,7 @@ and is similar to an ``if-else`` statement written in Python:: # .otherwise(alt.value("lightgray")) color = alt.value("lightgray") -As a convenience, -simple conditions may be expressed without defining a default: +Omitting the ``.otherwise()`` clause will use the channel default instead: .. altair-plot:: @@ -218,7 +217,7 @@ simple conditions may be expressed without defining a default: ) points -Multiple conditional branches (``elif`` in Python) +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. From aa3b283ca3574cf9ceb489f130792fec697229a2 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:25:00 -0700 Subject: [PATCH 33/38] Remove redundant example --- doc/user_guide/interactions/parameters.rst | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 54f2bc7dd..1724431b2 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -221,16 +221,8 @@ 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. -For now, you can use this pseudocode -as an example of what the syntax would look like:: - alt.when(brush1) - .then(alt.value("goldenrod")) - .when(brush2) - .then(alt.value("crimson")) - .otherwise(alt.value("grey")) - -More advanced usage can be found +More advanced use of conditions can be found in the :func:`when` API reference and in these gallery examples: From 6018196ad12570aa923444aa669ad6deafc24c4d Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:33:04 -0700 Subject: [PATCH 34/38] Remove non-working example of empty selections --- doc/user_guide/interactions/parameters.rst | 58 ++++------------------ 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 1724431b2..e418fc04f 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -579,71 +579,34 @@ Parameter Composition Altair also supports combining multiple parameters using the ``&``, ``|`` and ``~`` for respectively ``AND``, ``OR`` and ``NOT`` logical composition operands. -These parameter compositions can be used with both filters and conditions in Altair. -In the following example, -only the points that fall within the interval selections of both the scatter plots -will be counted in the bar chart -(so you will need to make a selection in both charts -before the bars shows up). - -.. altair-plot:: - - # empty=False ensure that no points are selected before a selection is drawn - brush = alt.selection_interval(empty=False) - brush2 = alt.selection_interval(empty=False) - - points = alt.Chart(cars).mark_point(size=10).encode( - x='Horsepower:Q', - y='Miles_per_Gallon:Q', - color='Origin:N' - ) - - points2 = points.encode( - x='Acceleration:Q', - y='Miles_per_Gallon:Q', - ) - bars = alt.Chart(cars).mark_bar().encode( - x='count()', - y='Origin:N', - color='Origin:N' - ).transform_filter( - brush & brush2 - ) - - (points.add_params(brush) | points2.add_params(brush2)) & bars - -To illustrate how a more complex parameter composition -can be applied to a conditional encoding, -we can return to our heatmap example. -Let's construct a scenario where there are two people who can make an interval +Returning to our heatmap examples, +we can construct a scenario where there are two people who can make an interval selection in the same chart. The person Alex makes a selection box when the alt-key (macOS: option-key) is selected and Morgan can make a selection box when the shift-key is selected. -Now, we color the chart marks when they fall within Alex's or Morgan's -selection, but not both's +We use :class:`BrushConfig` to give the selection box of Morgan a different +style. +Now, we color the rectangles when they fall within Alex's or Morgan's +selection (note that you need to create both selections before seeing the effect). -Here, we also use We use :class:`BrushConfig` to give the selection box of Morgan a different -style to be able to tell them apart. .. altair-plot:: alex = alt.selection_interval( on="[pointerdown[event.altKey], pointerup] > pointermove", - empty=False, + name='alex' ) morgan = alt.selection_interval( on="[pointerdown[event.shiftKey], pointerup] > pointermove", mark=alt.BrushConfig(fill="#fdbb84", fillOpacity=0.5, stroke="#e34a33"), - empty=False, + name='morgan' ) - exlusive_or = (alex | morgan) & ~(alex & morgan) - alt.Chart(cars).mark_rect().encode( x='Cylinders:O', y='Origin:O', - color=alt.when(exlusive_or).then("count()").otherwise(alt.value("grey")), + color=alt.condition(alex | morgan, 'count()', alt.ColorValue("grey")) ).add_params( alex, morgan ).properties( @@ -653,10 +616,9 @@ style to be able to tell them apart. With these operators, selections can be combined in arbitrary ways: -- ``alex | morgan``: to select the rectangles that fall inside either - Alex's or Morgans' selection. - ``~(alex & morgan)``: to select the rectangles that fall outside Alex's and Morgan's selections. + - ``alex | ~morgan``: to select the rectangles that fall within Alex's selection or outside the selection of Morgan From 852ebff36c15002cdb9b5b23edefb65399eb5393 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 2 Oct 2024 20:55:39 -0700 Subject: [PATCH 35/38] Clarify wording --- doc/user_guide/interactions/parameters.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index e418fc04f..eda1fc6b5 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -388,7 +388,8 @@ empty selection contains none of the points: make_example(interval_x) The ``empty=False`` argument could instead be set inside :func:`when`, -so that you don't need to redefine the same selection, e.g.:: +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() ... From c3f8a6274d6eb7d0af22b381576fefdd026171de Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Thu, 3 Oct 2024 15:26:30 +0100 Subject: [PATCH 36/38] revert: Restore `condition` -> `when` from 1d6be1665348e6f31e25b23e89659fc2fe245d5f Seems there was an unintended revert in https://github.com/vega/altair/pull/3544/commits/6018196ad12570aa923444aa669ad6deafc24c4d --- doc/user_guide/interactions/parameters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index eda1fc6b5..8ebb30146 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -607,7 +607,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( From 1a8c59ae72d22eda49278296e89e654abb4c1b9d Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Sat, 2 Nov 2024 11:45:15 +0000 Subject: [PATCH 37/38] style: Revert style changes in examples https://github.com/vega/altair/pull/3544#discussion_r1825653011, https://github.com/vega/altair/pull/3544#discussion_r1825653317, https://github.com/vega/altair/pull/3544#discussion_r1825653932, https://github.com/vega/altair/pull/3544#discussion_r1825656803, https://github.com/vega/altair/pull/3544#discussion_r1825658668 --- .../bar_chart_with_highlighted_bar.py | 12 ++--- .../bar_chart_with_negatives.py | 12 ++--- .../scatter_point_paths_hover.py | 13 +++-- .../waterfall_chart.py | 49 +++++++++---------- .../scatter_point_paths_hover.py | 13 +++-- 5 files changed, 49 insertions(+), 50 deletions(-) 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 511f44f15..1041fb99f 100644 --- a/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py +++ b/tests/examples_arguments_syntax/bar_chart_with_highlighted_bar.py @@ -14,10 +14,8 @@ # otherwise, use `"steelblue"` color = alt.when(year=1810).then(alt.value("orange")).otherwise(alt.value("steelblue")) -chart = ( - alt.Chart(source) - .mark_bar() - .encode(x="year:O", y="wheat:Q", color=color) - .properties(width=600) -) -chart \ No newline at end of file +alt.Chart(source).mark_bar().encode( + x="year:O", + y="wheat:Q", + 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 647b67c76..d3ff3fbc5 100644 --- a/tests/examples_arguments_syntax/bar_chart_with_negatives.py +++ b/tests/examples_arguments_syntax/bar_chart_with_negatives.py @@ -12,10 +12,8 @@ predicate = alt.datum.nonfarm_change > 0 color = alt.when(predicate).then(alt.value("steelblue")).otherwise(alt.value("orange")) -chart = ( - alt.Chart(source) - .mark_bar() - .encode(x="month:T", y="nonfarm_change:Q", color=color) - .properties(width=600) -) -chart \ No newline at end of file +alt.Chart(source).mark_bar().encode( + x="month:T", + y="nonfarm_change:Q", + color=color +).properties(width=600) diff --git a/tests/examples_arguments_syntax/scatter_point_paths_hover.py b/tests/examples_arguments_syntax/scatter_point_paths_hover.py index fd8f0a8bf..aea0960f6 100644 --- a/tests/examples_arguments_syntax/scatter_point_paths_hover.py +++ b/tests/examples_arguments_syntax/scatter_point_paths_hover.py @@ -60,11 +60,14 @@ .otherwise(alt.value(0.1)) ) # Points that are always visible (filtered by slider and search) -visible_points = ( - base.mark_circle(size=100) - .encode(opacity=opacity) - .transform_filter(x_select) - .add_params(hover, hover_point_opacity, x_select) +visible_points = base.mark_circle(size=100).encode( + opacity=opacity + ).transform_filter( + x_select + ).add_params( + hover, + hover_point_opacity, + x_select ) when_hover = alt.when(hover) diff --git a/tests/examples_arguments_syntax/waterfall_chart.py b/tests/examples_arguments_syntax/waterfall_chart.py index 835b194e9..bc01e04d4 100644 --- a/tests/examples_arguments_syntax/waterfall_chart.py +++ b/tests/examples_arguments_syntax/waterfall_chart.py @@ -42,23 +42,19 @@ ) # 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=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)) +base_chart = alt.Chart(source).transform_window( + window_sum_amount="sum(amount)", + window_lead_label="lead(label)", +).transform_calculate( + 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) ) color_coding = ( @@ -96,12 +92,13 @@ color=alt.value("white"), ) -waterfall = ( - bar - + rule - + text_pos_values_top_of_bar - + text_neg_values_bot_of_bar - + text_bar_values_mid_of_bar -).properties(width=800, height=450) - -waterfall \ No newline at end of file +alt.layer( + bar, + rule, + text_pos_values_top_of_bar, + text_neg_values_bot_of_bar, + text_bar_values_mid_of_bar +).properties( + width=800, + height=450 +) \ No newline at end of file diff --git a/tests/examples_methods_syntax/scatter_point_paths_hover.py b/tests/examples_methods_syntax/scatter_point_paths_hover.py index 713792401..c6a9c5f19 100644 --- a/tests/examples_methods_syntax/scatter_point_paths_hover.py +++ b/tests/examples_methods_syntax/scatter_point_paths_hover.py @@ -60,11 +60,14 @@ .otherwise(alt.value(0.1)) ) # Points that are always visible (filtered by slider and search) -visible_points = ( - base.mark_circle(size=100) - .encode(opacity=opacity) - .transform_filter(x_select) - .add_params(hover, hover_point_opacity, x_select) +visible_points = base.mark_circle(size=100).encode( + opacity=opacity + ).transform_filter( + x_select + ).add_params( + hover, + hover_point_opacity, + x_select ) when_hover = alt.when(hover) From 83a3a64da9e15f0fce369dfeab20abc64be4868a Mon Sep 17 00:00:00 2001 From: dangotbanned <125183946+dangotbanned@users.noreply.github.com> Date: Sat, 2 Nov 2024 12:46:31 +0000 Subject: [PATCH 38/38] style: Revert style changes in user guide https://github.com/vega/altair/pull/3544#discussion_r1825666513, https://github.com/vega/altair/pull/3544#discussion_r1825666641, https://github.com/vega/altair/pull/3544#discussion_r1825666004, https://github.com/vega/altair/pull/3544#discussion_r1825666103, https://github.com/vega/altair/pull/3544#discussion_r1825663695, https://github.com/vega/altair/pull/3544#discussion_r1825663427, https://github.com/vega/altair/pull/3544#discussion_r1825664959, https://github.com/vega/altair/pull/3544#discussion_r1825665411 --- doc/case_studies/exploring-weather.rst | 45 ++++++++++------------ doc/user_guide/compound_charts.rst | 19 ++++----- doc/user_guide/interactions/parameters.rst | 17 ++++---- doc/user_guide/transform/filter.rst | 30 +++++++-------- doc/user_guide/transform/pivot.rst | 16 ++++---- 5 files changed, 63 insertions(+), 64 deletions(-) diff --git a/doc/case_studies/exploring-weather.rst b/doc/case_studies/exploring-weather.rst index 058085faa..ad2a3bc2d 100644 --- a/doc/case_studies/exploring-weather.rst +++ b/doc/case_studies/exploring-weather.rst @@ -226,33 +226,30 @@ of the selection (for more information on selections, see .. altair-plot:: brush = alt.selection_interval() - color = ( - alt.when(brush) - .then(alt.Color("weather:N").scale(scale)) - .otherwise(alt.value("lightgray")) + 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=temp_range + ).add_params( + brush ) - 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=color, - size=alt.Size("precipitation:Q").scale(range=[1, 200]), - ) - .transform_calculate("temp_range", "datum.temp_max - datum.temp_min") - .properties(width=600, height=400) - .add_params(brush) - ) - bars = ( - alt.Chart() - .mark_bar() - .encode(x="count()", y="weather:N", color=alt.Color("weather:N").scale(scale)) - .transform_calculate("temp_range", "datum.temp_max - datum.temp_min") - .transform_filter(brush) - .properties(width=600) + bars = alt.Chart(width=600).mark_bar().encode( + x="count()", + y="weather:N", + color=color + ).transform_calculate( + temp_range=temp_range + ).transform_filter( + brush ) + alt.vconcat(points, bars, data=df) This chart, containing concatenations, data transformations, selections, and diff --git a/doc/user_guide/compound_charts.rst b/doc/user_guide/compound_charts.rst index 171e83f28..a39114d38 100644 --- a/doc/user_guide/compound_charts.rst +++ b/doc/user_guide/compound_charts.rst @@ -366,21 +366,22 @@ layered chart with a hover selection: 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=when_hover.then("species:N").otherwise(alt.value("lightgray")), - ) - .properties(width=180, height=180) + base = alt.Chart(iris).encode( + x='petalLength:Q', + y='petalWidth:Q', + color=when_hover.then("species:N").otherwise(alt.value("lightgray")) + ).properties( + width=180, + height=180, ) + points = base.mark_point().add_params(hover) + text = base.mark_text(dy=-5).encode( text="species:N", opacity=when_hover.then(alt.value(1)).otherwise(alt.value(0)), ) - + (points + text).facet("species:N") Though each of the above examples have faceted the data across columns, diff --git a/doc/user_guide/interactions/parameters.rst b/doc/user_guide/interactions/parameters.rst index 8ebb30146..cf42d572b 100644 --- a/doc/user_guide/interactions/parameters.rst +++ b/doc/user_guide/interactions/parameters.rst @@ -172,7 +172,9 @@ a conditional color encoding: x="Horsepower:Q", y="Miles_per_Gallon:Q", color=conditional, - ).add_params(brush) + ).add_params( + brush + ) 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* @@ -207,14 +209,15 @@ Omitting the ``.otherwise()`` clause will use the channel default instead: source = data.cars() brush = alt.selection_interval() - color = alt.when(brush).then(alt.value('goldenrod')) - points = ( - alt.Chart(source) - .mark_point() - .encode(x="Horsepower", y="Miles_per_Gallon", color=color) - .add_params(brush) + 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) diff --git a/doc/user_guide/transform/filter.rst b/doc/user_guide/transform/filter.rst index 73f43ae16..fb4c7420f 100644 --- a/doc/user_guide/transform/filter.rst +++ b/doc/user_guide/transform/filter.rst @@ -135,23 +135,23 @@ 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) - .transform_filter(selection) - ) - color = ( - alt.when(selection).then(alt.value("steelblue")).otherwise(alt.value("lightgray")) + 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=color) - .properties(width=600, height=100) - .add_params(selection) + + 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) Logical Operands diff --git a/doc/user_guide/transform/pivot.rst b/doc/user_guide/transform/pivot.rst index 24258cb82..eb280d1e5 100644 --- a/doc/user_guide/transform/pivot.rst +++ b/doc/user_guide/transform/pivot.rst @@ -56,15 +56,13 @@ values on multiple lines: 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.when(selection).then(alt.value(0.3)).otherwise(alt.value(0)), - tooltip=[alt.Tooltip(c, type="quantitative") for c in columns], - ) - .add_params(selection) - ) + rule = base.transform_pivot( + 'symbol', value='price', groupby=['date'] + ).mark_rule().encode( + 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