You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Altair交互式图表中添加分类选中/未选中占比饼图?

最优实现方案:独立饼图+数据转换绑定选择器

核心问题在于row分面默认共享数据源和编码规则,没法给每个子图单独设置过滤条件与选中状态计算逻辑。改用独立饼图模板+针对性数据转换的方案,能精准实现需求:

实现步骤

  1. 定义区间选择器:保持原有的交互逻辑,绑定散点图
  2. 数据转换:给每个饼图添加独立的过滤和选中状态计算
  3. 复用饼图模板:减少冗余代码,分别适配三个饼图的需求
  4. 组合布局:用水平/垂直拼接工具整合图表,独立管理颜色比例尺

代码示例

import altair as alt
from vega_datasets import data

# 模拟带A/B分类的数据集
df = data.iris()
df['category'] = df['species'].map({'setosa': 'A', 'versicolor': 'B', 'virginica': 'B'})

# 定义区间选择器
brush = alt.selection_interval(name='brush')

# 散点图(保留原交互)
scatter = alt.Chart(df).mark_circle(size=60).encode(
    x='petalLength',
    y='petalWidth',
    color='category:N'
).add_params(brush)

# ----------------------
# 饼图1:选中点的A/B分类占比
# ----------------------
pie_selected_category = alt.Chart(df).mark_arc().encode(
    theta=alt.Theta(aggregate='count', type='quantitative'),
    color='category:N',
    tooltip=['category:N', alt.Tooltip(aggregate='count', type='quantitative', title='数量')]
).transform_filter(brush).properties(title='选中点的A/B分类占比')

# ----------------------
# 饼图2:A类数据的选中/未选中占比
# ----------------------
pie_a_status = alt.Chart(df).mark_arc().encode(
    theta=alt.Theta(aggregate='count', type='quantitative'),
    color=alt.Color('is_selected:N', scale=alt.Scale(
        domain=['True', 'False'],
        range=['#1f77b4', '#cccccc']  # A类原色+灰色
    )),
    tooltip=['is_selected:N', alt.Tooltip(aggregate='count', type='quantitative', title='数量')]
).transform_filter(alt.FieldEqualPredicate(field='category', equal='A')).transform_calculate(
    is_selected=f"brush('{brush.name}').test(datum)"
).properties(title='A类数据的选中/未选中占比')

# ----------------------
# 饼图3:B类数据的选中/未选中占比
# ----------------------
pie_b_status = alt.Chart(df).mark_arc().encode(
    theta=alt.Theta(aggregate='count', type='quantitative'),
    color=alt.Color('is_selected:N', scale=alt.Scale(
        domain=['True', 'False'],
        range=['#ff7f0e', '#cccccc']  # B类原色+灰色
    )),
    tooltip=['is_selected:N', alt.Tooltip(aggregate='count', type='quantitative', title='数量')]
).transform_filter(alt.FieldEqualPredicate(field='category', equal='B')).transform_calculate(
    is_selected=f"brush('{brush.name}').test(datum)"
).properties(title='B类数据的选中/未选中占比')

# 组合布局:散点图 + 垂直排列的三个饼图
dashboard = alt.hconcat(
    scatter,
    alt.vconcat(pie_selected_category, pie_a_status, pie_b_status, spacing=20)
).resolve_scale(color='independent')  # 独立设置每个图表的颜色比例尺

dashboard.display()

关键细节说明

  • 为什么不用分面:分面是对同一数据源的分组展示,无法给每个子图单独添加transform_filter和transform_calculate逻辑,而新增的两个饼图需要分别过滤A/B类并计算选中状态,独立图表方案更灵活。
  • 颜色比例尺独立:通过resolve_scale(color='independent')避免三个饼图的颜色规则冲突,确保每个饼图的颜色符合需求。
  • 选中状态计算:用brush().test(datum)判断当前数据点是否在选择区间内,生成is_selected字段用于饼图统计。

内容的提问来源于stack exchange,提问作者Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 06:36:30