Reputation: 73
I want to create a plot with two dropdown menus. The opacity of the lines should depend on the selection in both dropdown menus.
Ideally the possible content of the second dropdown menu ("dropdown_symbol" below) should depend on the selection in the first dropdown (when "category_2" is selected in the first dropdown, only show "AMZM" and "IBM" in the second dropdown).
Unfortunately neither the opacities work properly nor the restriction of the possible content. Here is my sample code:
import altair as alt
from vega_datasets import data
source = data.stocks()
source.symbol.value_counts()
source["category"] = "category_1"
source.loc[source["symbol"].isin(["AMZN", "IBM"]), "category"] = "category_2"
dropdown_category = alt.binding_select(options=list(source["category"].unique()), name=" ")
dropdown_symbol = alt.binding_select(options=list(source["symbol"].unique()), name=" ")
selection_category = alt.selection_single(fields=["category"], bind=dropdown_category)
selection_symbol = alt.selection_single(fields=["symbol"], bind=dropdown_symbol)
chart = alt.Chart(source).mark_line().encode(
x='date',
y='price',
color='symbol',
opacity=alt.condition(
selection_category & selection_symbol,
alt.value(1),
alt.value(0.1)
)).add_selection(selection_symbol, selection_category)
chart
Upvotes: 3
Views: 2937
Reputation: 63
I have been struggling with making something similar work, and I guess there are others like me, so let me post my solution to the first part of your problem here.
To follow up on jakevdp's answer mentioning the bug in Vega-lite: there is a workaround described here. However, I couldn't find a way to translate that to proper Altair Python code, so I opted for writing the condition as a Vega spec in Json/embedded dicts format. The key here is to include the test
field.
Furthermore, you probably want a way to reset the selection. This can be done by including None
among the options, as described here.
The code below works for me with Altair 4.1.0.
import altair as alt
from vega_datasets import data
source = data.stocks()
source.symbol.value_counts()
source["category"] = "category_1"
source.loc[source["symbol"].isin(["AMZN", "IBM"]), "category"] = "category_2"
cat_values = list(source["category"].unique())
sym_values = list(source["symbol"].unique())
cat_options = [None] + cat_values
sym_options = [None] + sym_values
cat_labels = ["All"] + cat_values
sym_labels = ["All"] + sym_values
dropdown_category = alt.binding_select(options=cat_options, labels=cat_labels, name=" ")
dropdown_symbol = alt.binding_select(options=sym_options, labels=sym_labels, name=" ")
selection_category = alt.selection_single(fields=["category"], bind=dropdown_category, name="cat")
selection_symbol = alt.selection_single(fields=["symbol"], bind=dropdown_symbol, name="sym")
op_condition = {"condition":
{"test":
{"and":
[{"selection": "cat"},
{"selection": "sym"}]},
"value": 1},
"value": 0.1}
chart = alt.Chart(source).mark_line().encode(
x='date',
y='price',
color='symbol',
opacity=op_condition
).add_selection(selection_symbol, selection_category)
chart
Upvotes: 1
Reputation: 86300
I want to create a plot with two dropdown menus. The opacity of the lines should depend on the selection in both dropdown menus.
If you want the opacity to depend on the selection within two dropdown menus, you can use an alt.condition
statement and pass the two selection objects with a boolean operator; for example:
opacity=alt.condition(
selection1 & selection2,
alt.value(1),
alt.value(0.1))
will choose the first value only if the point is within both selections. Alternatively,
opacity=alt.condition(
selection1 | selection2,
alt.value(1),
alt.value(0.1))
will choose the first value if the point is within at least one of the selections.
Note that when using multiple selections in this way, there is a known bug around the behavior for empty selections; see https://github.com/altair-viz/altair/issues/1759 and references therein.
Ideally the possible content of the second dropdown menu ("dropdown_symbol" below) should depend on the selection in the first dropdown (when "category_2" is selected in the first dropdown, only show "AMZM" and "IBM" in the second dropdown).
It is not possible in Altair for the content of a dropdown menu to change dynamically based on the selection within another dropdown menu.
For this to change, the feature would have to be added to Vega-Lite: you can file feature requests here.
Upvotes: 2