如何在Altair交互式图表中添加分类选中/未选中占比饼图?
最优实现方案:独立饼图+数据转换绑定选择器
核心问题在于row分面默认共享数据源和编码规则,没法给每个子图单独设置过滤条件与选中状态计算逻辑。改用独立饼图模板+针对性数据转换的方案,能精准实现需求:
实现步骤
- 定义区间选择器:保持原有的交互逻辑,绑定散点图
- 数据转换:给每个饼图添加独立的过滤和选中状态计算
- 复用饼图模板:减少冗余代码,分别适配三个饼图的需求
- 组合布局:用水平/垂直拼接工具整合图表,独立管理颜色比例尺
代码示例
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
相关产品推荐
相关产品推荐

