如何在 Altair 中对属性使用条件选择?

How to use conditional selection for properties in Altair?

我正在尝试让线图响应图例上的选择并相应地更新其自身的某些部分。

下面我有一些失败的尝试:(

我想要实现的是:图例应该分成 'Country' 和 'Mode' 的可用选项,如 chart0。但是,我希望图表只绘制与所选模式相关的数据。我还想在选择某些选项时更改轴标签、比例和其他属性。我想我没有正确使用 alt.condition()

import pandas as pd
import altair as alt

df1 = pd.DataFrame({'foo':[2,4,3],'bar':[1,2,1]})
df2 = pd.DataFrame({'foo':[20,30,45],'bar':[50,10,40]})
df = pd.concat([df1, df2], axis=1)
col = pd.MultiIndex.from_arrays([['A', 'A', 'B', 'B'], ['foo','bar','foo','bar']])
df.columns = col
df = df.reset_index().melt('index', var_name=['Mode','Country'], value_name='myvalue').dropna()

country_selection = alt.selection_multi(fields=['Country'], bind='legend')
mode_selection = alt.selection_multi(fields=['Mode'], bind='legend')


chart0 = alt.Chart(df).mark_line().encode(
    x='index:Q',
    y = alt.Y('myvalue:Q', title='A'),
    color=alt.condition(country_selection, alt.Color('Country:N'), alt.value('lightgray')),
    opacity='Mode:N'
).add_selection(country_selection).add_selection(mode_selection).properties(width=300, height=300)


chart1 = alt.Chart(df).mark_line().encode(
    x='index:Q',
    y = alt.Y('myvalue:Q', title='A'),
    color=alt.condition(country_selection, alt.Color('Country:N'), alt.value('lightgray')),
).add_selection(country_selection).add_selection(mode_selection).transform_filter(mode_selection).properties(width=300, height=300)



chart2 = alt.Chart(df).mark_line().encode(
    x='index:Q',
    y = alt.Y('myvalue:Q', title=alt.condition(mode_selection, 'A', 'B')),
    color=alt.condition(country_selection, alt.Color('Country:N'), alt.value('lightgray')),
    opacity='Mode:N'
).add_selection(country_selection).add_selection(mode_selection).transform_filter(mode_selection).properties(width=300, height=300)
    

如果您只想绘制所选数据(根据数据内容调整轴),您可以使用 transform_filter 将图表限制为显示所选数据。

为了让未选择的数据出现在图例上,明确设置图例的比例域很重要:

country_selection = alt.selection_multi(fields=['Country'], bind='legend')
mode_selection = alt.selection_multi(fields=['Mode'], bind='legend')

alt.Chart(df).mark_line().encode(
    x='index:Q',
    y = alt.Y('myvalue:Q', title='A'),
    color=alt.Color('Country:N', scale=alt.Scale(domain=list(df.Country.unique()))),
    opacity=alt.Opacity('Mode:N', scale=alt.Scale(domain=list(df.Mode.unique())))
).add_selection(
    country_selection,
    mode_selection
).transform_filter(
    country_selection
).transform_filter(
    mode_selection
)