Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs to better describe how to use checkboxes and logic-based bindings in general #2926

Merged
merged 6 commits into from
Feb 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 115 additions & 88 deletions doc/user_guide/interactions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ Interactive charts can use one or more of these elements to create rich interact
Parameters: Building Blocks of Interaction
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Interactivity in Altair is built around *parameters*, of which there are two types: variables and selections. We introduce these concepts through a series examples.
Interactivity in Altair is built around *parameters*, of which there are two types: *variables* and *selections*. We introduce these concepts through a series examples.

.. note::

This material was changed considerably with the release of Altair 5. In particular, Altair 4 had selections but not variables, and the term ``parameter`` first appeared in Altair 5.
This material was changed considerably with the release of Altair 5. In particular, Altair 4 had selections but not variables, and the term "parameter" first appeared in Altair 5.

.. _basic variable:

Expand Down Expand Up @@ -512,7 +512,7 @@ depending on the size and position of the selection in the scatter plot.

brush = alt.selection_interval()

points = alt.Chart(cars).mark_circle().encode(
points = alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N'
Expand All @@ -531,26 +531,39 @@ depending on the size and position of the selection in the scatter plot.
points & bars


Binding: Adding Data Driven Inputs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With an understanding of the selection types and conditions, you can now add data-driven input elements to the charts using the ``bind`` option. As specified by `Vega-lite binding <https://vega.github.io/vega-lite/docs/bind.html#input-element-binding>`_, selections can be bound two-ways:
Binding: Adding Widgets to Drive Interactivity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With an understanding of the selection types and conditions, you can now add data-driven and logic-driven widgets (or "bindings") as input elements to the charts using the ``bind`` option. As specified by `Vega-lite binding <https://vega.github.io/vega-lite/docs/bind.html#input-element-binding>`_, bindings can be of three types:

1. Point selections can be bound directly to an input element, *for example, a radio button.*
2. Interval selections which can be bound to scale, *for example, zooming in on a map.*
1. Point and interval selections can be used for data-driven interactive elements, such as highlighting and filtering based on values in the data.
2. Sliders and checkboxes can be used for logic-driven interactive elements, such as highlighting and filtering based on the absolute values in these widgets.
3. Interval selections can be bound to a scale, such as zooming in on a map.
Comment on lines +534 to +540
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this restructuring make sense?


Input Element Binding
^^^^^^^^^^^^^^^^^^^^^
With point selections, an input element can be added to the chart to establish a binding between the input and the selection.
The following table summarizes the input elements that are supported in Vega-Lite:

========================= =========================================================================== ===============================================
Input Element Description Example
========================= =========================================================================== ===============================================
:class:`binding_checkbox` Renders as checkboxes allowing for multiple selections of items. :ref:`gallery_multiple_interactions`
:class:`binding_radio` Radio buttons that force only a single selection :ref:`gallery_multiple_interactions`
:class:`binding_select` Drop down box for selecting a single item from a list :ref:`gallery_multiple_interactions`
:class:`binding_range` Shown as a slider to allow for selection along a scale. :ref:`gallery_us_population_over_time`
========================= =========================================================================== ===============================================

For instance, using our example from above a dropdown can be used to highlight cars from a specific ``origin`` :

Data-Driven Input Element Binding
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With point selections, an input element can be added to the chart to establish a binding between the input and the selection. For instance, using our example from above, a dropdown can be used to highlight cars from a specific ``origin``:

.. altair-plot::

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.condition(
selection,
alt.Color('Origin:N', legend=None),
alt.value('lightgray')
)

alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
Expand All @@ -561,133 +574,147 @@ For instance, using our example from above a dropdown can be used to highlight c
selection
)




The above example shows all three elements at work. The ``input_dropdown`` is ``bind`` to the ``selection`` which is called from the ``condition`` encoded through the data.

The following are the input elements supported in vega-lite:


========================= =========================================================================== ===============================================
Input Element Description Example
========================= =========================================================================== ===============================================
:class:`binding_checkbox` Renders as checkboxes allowing for multiple selections of items. :ref:`gallery_multiple_interactions`
:class:`binding_radio` Radio buttons that force only a single selection :ref:`gallery_multiple_interactions`
:class:`binding_select` Drop down box for selecting a single item from a list :ref:`gallery_multiple_interactions`
:class:`binding_range` Shown as a slider to allow for selection along a scale. :ref:`gallery_us_population_over_time`
========================= =========================================================================== ===============================================

The above example shows all three elements at work. We ``bind`` the ``input_dropdown`` to the ``selection`` which is called from the ``condition`` encoded through the data.

Bindings and input elements can also be used to filter data on the client side. Reducing noise in the chart and allowing the user to see just certain selected elements:

.. altair-plot::

input_dropdown = alt.binding_select(options=['Europe','Japan','USA'], name='Region ')
# Make radio button less cramped by adding a space after each label
options = ['Europe', 'Japan', 'USA']
labels = [option + ' ' for option in options]

input_dropdown = alt.binding_radio(options=options, labels=labels, name='Region: ')
selection = alt.selection_point(fields=['Origin'], bind=input_dropdown)

alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
# We need to set a constant domain to preserve the colors
# when only one region is shown at a time
color=alt.Color('Origin:N', scale=alt.Scale(domain=options)),
tooltip='Name:N'
).add_params(
selection
).transform_filter(
selection
)

Logic-Driven Input Element Binding
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Scale Binding
^^^^^^^^^^^^^
With interval selections, the ``bind`` property can be set to the value of ``"scales"``. In these cases, the binding will automatically respond to the panning and zooming along the chart:
So far we have seen the use of selections to match values in our data.
When using checkbox bindings,
we want to instead use the state of the checkbox as a True/False condition
and execute some action depending on whether it is checked or not.
When we are using a checkbox as a toggle like this,
we need to use `param` instead of `selection_point`,
since we don't want to check if there are True/False values in our data,
just if the value of the check box is True (checked) or False (unchecked):

.. altair-plot::

selection = alt.selection_interval(bind='scales')
bind_checkbox = alt.binding_checkbox(name='Scale point size by "Acceleration": ')
param_checkbox = alt.param(bind=bind_checkbox)

alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
tooltip='Name:N'
size=alt.condition(
param_checkbox,
alt.Size('Acceleration:Q'),
alt.value(25)
)
).add_params(
selection
param_checkbox
)


Parameter Values in Expressions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Selection Parameters
^^^^^^^^^^^^^^^^^^^^

Selection values can be accessed directly and used in expressions that affect the
chart. For example, here we create a slider to choose a cutoff value, and color
points based on whether they are smaller or larger than the value:
Similarly, if we want to create a condition
where we use the value of a slider
we can use `param` like so:

.. altair-plot::

import altair as alt
import pandas as pd
import numpy as np
import numpy as np

rand = np.random.RandomState(42)
rand = np.random.RandomState(42)

df = pd.DataFrame({
'xval': range(100),
'yval': rand.randn(100).cumsum()
})
df = pd.DataFrame({
'xval': range(100),
'yval': rand.randn(100).cumsum()
})

slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.selection_point(name="SelectorName", fields=['cutoff'],
bind=slider, value=[{'cutoff': 50}])
slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.param(name='SelectorName', value=50, bind=slider)

alt.Chart(df).mark_point().encode(
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.datum.xval < selector,
# 'datum.xval < SelectorName', # An equivalent alternative
alt.value('red'), alt.value('blue')
)
).add_params(
).add_params(
selector
)
)

Selector values can be similarly used anywhere that expressions are valid, for
example, in a :ref:`user-guide-calculate-transform` or a
:ref:`user-guide-filter-transform`.
In this case we could also have used a selection
as selection values can be accessed directly and used in expressions that affect the
chart. For example, here we create a slider to choose a cutoff value, and color
points based on whether they are smaller or larger than the value:

Variable Parameters
^^^^^^^^^^^^^^^^^^^
.. altair-plot::

While it is useful to know
how to access selection parameter values
slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.selection_point(
name="SelectorName",
fields=['cutoff'],
bind=slider,
value=[{'cutoff': 50}]
)

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')
)
).add_params(
selector
)

While it can be useful to know
how to access selection values
in expression strings,
the variable parameters introduced in Altair 5
using the parameters syntax introduced in Altair 5
often provides a more convenient syntax
for simple interactions like this one
since they can also be accessed in expression strings:
since they can also be accessed in expression strings
as we saw above.
Selections and parameters can be used anywhere that expressions are valid, for
example, in a :ref:`user-guide-calculate-transform` or a
:ref:`user-guide-filter-transform`.

Scale Binding
^^^^^^^^^^^^^
With interval selections, the ``bind`` property can be set to the value of ``"scales"``. In these cases, the binding will automatically respond to the panning and zooming along the chart:

.. altair-plot::

slider = alt.binding_range(min=0, max=100, step=1, name='Cutoff ')
selector = alt.param(name='SelectorName', value=50, bind=slider)
selection = alt.selection_interval(bind='scales')

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')
)
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin:N',
tooltip='Name:N'
).add_params(
selector
selection
)


Further Examples
~~~~~~~~~~~~~~~~
Now that you understand the basics of Altair selections and bindings, you might wish to look
Expand Down
19 changes: 11 additions & 8 deletions tests/examples_arguments_syntax/multiple_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@
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_condition = alt.condition(
rating_select,
alt.Color('MPAA_Rating:N', legend=None),
alt.value('lightgray')
)

highlight_ratings = base.add_params(
rating_select
Expand All @@ -72,13 +74,14 @@
).properties(title="Radio Button Highlighting")

# Boolean selection for format changes
input_checkbox = alt.binding_checkbox(name="Big Budget Films")
input_checkbox = alt.binding_checkbox(name="Big Budget Films ")
checkbox_selection = alt.param(bind=input_checkbox)

size_checkbox_condition = alt.condition(checkbox_selection,
alt.SizeValue(25),
alt.Size('Hundred_Million_Production:Q')
)
size_checkbox_condition = alt.condition(
checkbox_selection,
alt.Size('Hundred_Million_Production:Q'),
alt.SizeValue(25)
)

budget_sizing = base.add_params(
checkbox_selection
Expand Down
11 changes: 6 additions & 5 deletions tests/examples_methods_syntax/multiple_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@
).properties(title="Radio Button Highlighting")

# Boolean selection for format changes
input_checkbox = alt.binding_checkbox(name="Big Budget Films")
input_checkbox = alt.binding_checkbox(name="Big Budget Films ")
checkbox_selection = alt.param(bind=input_checkbox)

size_checkbox_condition = alt.condition(checkbox_selection,
alt.SizeValue(25),
alt.Size('Hundred_Million_Production:Q')
)
size_checkbox_condition = alt.condition(
checkbox_selection,
alt.Size('Hundred_Million_Production:Q'),
alt.SizeValue(25)
Comment on lines +84 to +85
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched the order so that checking the box shows the big budget films instead of removes them

)

budget_sizing = base.add_params(
checkbox_selection
Expand Down