Python 组合悬停并单击Altair中的选择
我想在Altair绘图中组合悬停和单击选项。下面的代码生成了我想要的结果:默认情况下,点基本上是透明的,将鼠标悬停在点上会增加不透明度,然后单击该点会进一步增加不透明度。我发现这很有用,用户可以将鼠标悬停在某个点上以快速了解结果,然后单击该点以“锁定”选择。虽然我对结果感到满意,但该方法似乎有点麻烦,因为我需要为悬停和单击选择定义不同的图表层。如果我可以构造一个多路条件表达式,那么我似乎可以大大简化代码。我尝试将不透明度条件写为Python 组合悬停并单击Altair中的选择,python,altair,vega-lite,Python,Altair,Vega Lite,我想在Altair绘图中组合悬停和单击选项。下面的代码生成了我想要的结果:默认情况下,点基本上是透明的,将鼠标悬停在点上会增加不透明度,然后单击该点会进一步增加不透明度。我发现这很有用,用户可以将鼠标悬停在某个点上以快速了解结果,然后单击该点以“锁定”选择。虽然我对结果感到满意,但该方法似乎有点麻烦,因为我需要为悬停和单击选择定义不同的图表层。如果我可以构造一个多路条件表达式,那么我似乎可以大大简化代码。我尝试将不透明度条件写为alt.condition(单击选择,单击不透明度,alt.cond
alt.condition(单击选择,单击不透明度,alt.condition(悬停选择,悬停不透明度,默认不透明度))
,但出现了一个错误。有没有一种方法可以简化我下面的代码来组合悬停和单击选择
import altair as alt
import numpy as np
import pandas as pd
a_values = np.arange(1, 4)
x_values = np.linspace(0, 2, 1000)
DEFAULT_OPACITY = 0.3
HOVER_OPACITY = 0.5
CLICK_OPACITY = 1.0
a_df = pd.DataFrame({'a': a_values})
df = pd.DataFrame({
'a': np.tile(A=a_values, reps=len(x_values)),
'x': np.repeat(a=x_values, repeats=len(a_values)),
})
df['y'] = df['a'] * np.sin(2 * np.pi * df['x'])
hover_selection = alt.selection_single(
clear='mouseout',
empty='none',
fields=['a'],
name='hover_selection',
on='mouseover',
)
click_selection = alt.selection_single(
empty='none',
fields=['a'],
name='click_selection',
on='click',
)
a_base = alt.Chart(a_df).mark_point(
filled=True, size=100,
).encode(
x=alt.X(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
y=alt.Y(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
)
a_hover = a_base.encode(
opacity=alt.condition(hover_selection, alt.value(HOVER_OPACITY), alt.value(DEFAULT_OPACITY))
).add_selection(hover_selection)
a_click = a_base.encode(
opacity=alt.condition(click_selection, alt.value(CLICK_OPACITY), alt.value(0.0)),
).add_selection(click_selection)
y_base = alt.Chart(df).mark_line().encode(
x=alt.X(shorthand='x:Q', scale=alt.Scale(domain=(0, 2))),
y=alt.Y(shorthand='y:Q', scale=alt.Scale(domain=(-3, 3))),
)
y_hover = y_base.encode(
opacity=alt.value(HOVER_OPACITY),
).transform_filter(hover_selection)
y_click = y_base.encode(
opacity=alt.value(CLICK_OPACITY),
).transform_filter(click_selection)
alt.hconcat(
alt.layer(a_hover, a_click),
alt.layer(y_hover, y_click),
)
VegaLite支持在相同条件下进行多个选择,但我认为不可能在
alt.condition
中编写。但是,您可以看到,alt.Condition
返回一个字典,因此您可以直接通过一个选择列表来编写它
这样你就可以澄清这一部分
a_base = alt.Chart(a_df).mark_point(
filled=True, size=100,
).encode(
x=alt.X(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
y=alt.Y(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
)
a_hover = a_base.encode(
opacity=alt.condition(hover_selection, alt.value(HOVER_OPACITY), alt.value(DEFAULT_OPACITY))
).add_selection(hover_selection)
a_click = a_base.encode(
opacity=alt.condition(click_selection, alt.value(CLICK_OPACITY), alt.value(0.0)),
).add_selection(click_selection)
y_base = alt.Chart(df).mark_line().encode(
x=alt.X(shorthand='x:Q', scale=alt.Scale(domain=(0, 2))),
y=alt.Y(shorthand='y:Q', scale=alt.Scale(domain=(-3, 3))),
)
y_hover = y_base.encode(
opacity=alt.value(HOVER_OPACITY),
).transform_filter(hover_selection)
y_click = y_base.encode(
opacity=alt.value(CLICK_OPACITY),
).transform_filter(click_selection)
alt.hconcat(
alt.layer(a_hover, a_click),
alt.layer(y_hover, y_click),
)
对这样的事情:
hover_and_click_condition = {
'condition': [
{'selection': 'hover_selection', 'value': HOVER_OPACITY},
{'selection': 'click_selection', 'value': CLICK_OPACITY}],
'value': DEFAULT_OPACITY}
a = alt.Chart(a_df).mark_point(
filled=True, size=100,
).encode(
x=alt.X(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
y=alt.Y(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
opacity=hover_and_click_condition
).add_selection(hover_selection, click_selection)
y = alt.Chart(df).mark_line().encode(
x=alt.X(shorthand='x:Q', scale=alt.Scale(domain=(0, 2))),
y=alt.Y(shorthand='y:Q', scale=alt.Scale(domain=(-3, 3))),
opacity=hover_and_click_condition
)
a | (y.transform_filter(click_selection) + y.transform_filter(hover_selection))
对于变换过滤器,您可以重写此部分
a_base = alt.Chart(a_df).mark_point(
filled=True, size=100,
).encode(
x=alt.X(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
y=alt.Y(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
)
a_hover = a_base.encode(
opacity=alt.condition(hover_selection, alt.value(HOVER_OPACITY), alt.value(DEFAULT_OPACITY))
).add_selection(hover_selection)
a_click = a_base.encode(
opacity=alt.condition(click_selection, alt.value(CLICK_OPACITY), alt.value(0.0)),
).add_selection(click_selection)
y_base = alt.Chart(df).mark_line().encode(
x=alt.X(shorthand='x:Q', scale=alt.Scale(domain=(0, 2))),
y=alt.Y(shorthand='y:Q', scale=alt.Scale(domain=(-3, 3))),
)
y_hover = y_base.encode(
opacity=alt.value(HOVER_OPACITY),
).transform_filter(hover_selection)
y_click = y_base.encode(
opacity=alt.value(CLICK_OPACITY),
).transform_filter(click_selection)
alt.hconcat(
alt.layer(a_hover, a_click),
alt.layer(y_hover, y_click),
)
像这样:
hover_and_click_condition = {
'condition': [
{'selection': 'hover_selection', 'value': HOVER_OPACITY},
{'selection': 'click_selection', 'value': CLICK_OPACITY}],
'value': DEFAULT_OPACITY}
a = alt.Chart(a_df).mark_point(
filled=True, size=100,
).encode(
x=alt.X(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
y=alt.Y(shorthand='a:Q', scale=alt.Scale(domain=(min(a_values) - 1, max(a_values) + 1))),
opacity=hover_and_click_condition
).add_selection(hover_selection, click_selection)
y = alt.Chart(df).mark_line().encode(
x=alt.X(shorthand='x:Q', scale=alt.Scale(domain=(0, 2))),
y=alt.Y(shorthand='y:Q', scale=alt.Scale(domain=(-3, 3))),
opacity=hover_and_click_condition
)
a | (y.transform_filter(click_selection) + y.transform_filter(hover_selection))
您可以使用来组合依赖于多个输入的逻辑组合的条件,但我认为没有办法让它们触发不同的输出。我看看能不能马上举个例子。谢谢你看!我遇到的一个问题是,如果我单击左侧绘图上的一个点,然后将鼠标悬停在左侧绘图上的另一个点上,则右侧绘图上两条曲线之间的区域将着色。我正在使用JupyterLab 1.2.6,如果这有什么不同的话(尽管我不确定如何检查Vega lite版本)。@Stirling是的,这就是我提到的警告的意思:“但是如果你对一个细微的差异(当选择一个点并将鼠标悬停在另一个点上时,线之间的增量高亮显示),…”。我没有找到其他方法来简化第二部分,只有第一部分。@Stirling实际上我只是想到了一个解决方案。与我第一次写的内容相比,它略显冗长,但结果与你的问题完全相同,我编辑了我的答案。