【问题标题】:Interactive plot selection in Altair does not hi-light pointsAltair 中的交互式绘图选择不会突出显示点
【发布时间】:2018-09-09 00:20:03
【问题描述】:

我正在尝试在 Altair 中生成 2 个共享相同 selection 的图。

我想绘制人口 (y) 与年龄 (x) 的散点图和条形图。我正在使用 Altair 内置数据集population。总体是此数据集中people 列的总和。该数据集包含yearpeopleagesex 的列。我可以使用sum(people) 获得总填充量并将其绘制为yage。对于条形图,我可以使用sex 列类似地绘制sum(people) 与年龄和颜色的关系。

我正在尝试在这两个图之间设置一个画笔/选择,以便我可以在散点图中突出显示,同时更新条形图以反映该选择。但是,我遇到了以下问题

我使用 Altair 文档中的 layered bar graph example 作为示例。

这里是代码

import altair as alt
from altair.expr import datum, if_
from vega_datasets import data
interval = alt.selection_interval(encodings=['x', 'y'])

df = data.population.url

scatter = alt.Chart(df).mark_point().encode(
    alt.X('age:O', axis=alt.Axis(title='')),
    y='sum(people)',
    color=alt.condition(interval, 'sex:N', alt.value('lightgrey'))
).transform_filter(
    filter = datum.year == 2000
).transform_calculate(
    "sex", if_(datum.sex == 2, 'Female', 'Male')
).properties(
    selection=interval
)

bar = alt.Chart(df).mark_bar(opacity=0.7).encode(
    alt.X('age:O', scale=alt.Scale(rangeStep=17)),
    alt.Y('sum(people)', stack=None),
    color=alt.condition(interval, 'sex:N', alt.value('lightgrey')),
).transform_filter(
    filter = datum.year == 2000
).transform_calculate(
    "sex", if_(datum.sex == 2, 'Female', 'Male')
).properties(height=100, width=400)

scatter & bar

我已经修改了文档示例中的代码。我首先创建一个散点图,然后使用基于selection 的颜色。然后我定义了相同 2 列的条形图,并再次使用 selection 指定颜色。这是输出

现在,我想在顶部(散点)图上拖动一个框以选择一些点,同时底部(条形)图表应根据 selection 更新。当我拖入顶部的情节以制作我的selection 时,会发生这种情况

问题

  1. 在顶部绘图中拖动以进行选择后,两个绘图中的颜色(选择内部和外部)都更改为lightgrey。我预计,在这两个图中,选择/画笔内部都会被突出显示,但外部应该是 lightgrey

如何获得同时在顶部和底部图中突出显示的选择?

编辑

我想要this behaviour,其中一个情节中的画笔/选择同时在第二个(链接的)情节中突出显示。

软件包版本:

Python = 3.6
Altair = 2.2
Jupyter = 5.6

【问题讨论】:

    标签: python interactive vega-lite altair


    【解决方案1】:

    要触发对聚合值的选择,最好的方法是使用聚合转换来定义该数量,以便它可用于整个图表。

    这是一个例子:

    import altair as alt
    from altair.expr import datum, if_
    from vega_datasets import data
    
    interval = alt.selection_interval(encodings=['x', 'y'])
    
    
    base = alt.Chart(data.population.url).transform_filter(
        filter = datum.year == 2000
    ).transform_calculate(
        "sex", if_(datum.sex == 2, 'Female', 'Male')
    ).transform_aggregate(
        population="sum(people)",
        groupby=['age', 'sex']
    )
    
    scatter = base.mark_point().encode(
        alt.X('age:O', title=''),
        y='population:Q',
        color=alt.condition(interval, 'sex:N', alt.value('lightgrey'))
    ).properties(
        selection=interval
    )
    
    bar = base.mark_bar(opacity=0.7).encode(
        alt.X('age:O', scale=alt.Scale(rangeStep=17)),
        alt.Y('population:Q'),
        color=alt.condition(interval, 'sex:N', alt.value('lightgrey')),
    ).properties(height=100, width=400)
    
    scatter & bar
    

    请注意,我通过下图的间隔选择取消了过滤,因为这不是您描述的行为。

    【讨论】:

    • 非常感谢。这是一个非常明确的方法。 transform_aggregate() 看起来很有用。你让我从文档中想到了一个类似的例子,我可以在这里调整和使用(我认为)。我会在下面发布。
    • 同意在底部间隔触发过滤器 - 我会从问题中删除它......它不需要。
    【解决方案2】:

    基于(并调整)上述@jakevdp 的答案,我尝试了类似于文档库交互式图表部分中的this example 的内容。

    我没有使用base 对象,而是使用vconcat 函数,它连接Chart 实例并将转换和数据传递给vconcat 对象。这是方法

    import altair as alt
    from altair.expr import datum, if_
    from vega_datasets import data
    interval = alt.selection_interval(encodings=['x', 'y'])
    
    scatter = alt.Chart().mark_point().encode(
        alt.X('age:O', title=''),
        y='population:Q',
        color=alt.condition(interval, 'sex:N', alt.value('lightgrey'))
    ).properties(
        selection=interval
    )
    
    bar = alt.Chart().mark_bar(opacity=0.7).encode(
        alt.X('age:O', scale=alt.Scale(rangeStep=17)),
        alt.Y('population:Q'),
        color=alt.condition(interval, 'sex:N', alt.value('lightgrey')),
    ).properties(height=100, width=400)
    
    alt.vconcat(scatter, bar,
        data=data.population.url
    ).transform_filter(
        filter = datum.year == 2000
    ).transform_calculate(
        "sex", if_(datum.sex == 2, 'Female', 'Male')
    ).transform_aggregate(
        population="sum(people)",
        groupby=['age', 'sex']
    )
    

    这种方法似乎提供了与@jakevdp 的答案相同的功能。即可以对散点图(顶部)进行选择,这将根据需要反映在条形图(底部)中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 2015-05-03
      • 2020-05-07
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      相关资源
      最近更新 更多