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

如何用Altair绘制并排分组直方图并将Y轴设为百分比

用Altair创建并排分组直方图(Y轴显示百分比)

问题描述

需要创建并排分组直方图(两个类别在同一分箱区间内的柱子并排显示),Y轴显示每个类别的百分比而非计数,但当前代码生成的是分面柱图,无法合并为单张图,同时希望优化百分比的计算方式。

当前尝试的代码:

import pandas as pd
import numpy as np
import altair as alt

# Generate some example data
true_scores = np.random.normal(1, 2, 1000)
false_scores = np.random.normal(-2, 3, 1000)
scores = np.concatenate((true_scores, false_scores))
labels = [True] * 1000 + [False] * 1000
df = pd.DataFrame({"score": scores, "label": labels})

# make plot
alt.Chart(df).transform_joinaggregate(
    total='count(*)',
    groupby=['label']
).transform_calculate(
    pct='1 / datum.total'
).mark_bar().encode(
    x=alt.X("label:N", axis=alt.Axis(title=None, labels=False)),
    y=alt.Y("sum(pct):Q", axis=alt.Axis(title="Count")),
    color=alt.Color('label:N'),
    column=alt.Column('score:Q', bin=alt.Bin(maxbins=100), header=alt.Header(labelOrient="bottom")), 
)

解决方案

要实现并排分组直方图并显示百分比,需要调整分箱方式、百分比计算逻辑,同时去掉分面(column)改用分组编码:

完整代码

import pandas as pd
import numpy as np
import altair as alt

# 生成示例数据
true_scores = np.random.normal(1, 2, 1000)
false_scores = np.random.normal(-2, 3, 1000)
scores = np.concatenate((true_scores, false_scores))
labels = [True] * 1000 + [False] * 1000
df = pd.DataFrame({"score": scores, "label": labels})

alt.Chart(df).transform_bin(
    # 对score统一分箱,确保两个类别使用相同的区间
    'binned_score', field='score', bin=alt.Bin(maxbins=20)
).transform_joinaggregate(
    # 计算每个(label, 分箱区间)的样本数
    bin_count='count()',
    groupby=['label', 'binned_score']
).transform_joinaggregate(
    # 计算每个label的总样本数
    total='count()',
    groupby=['label']
).transform_calculate(
    # 计算当前分箱占该label的百分比
    pct='datum.bin_count / datum.total'
).mark_bar(
    # 设置柱子宽度,优化并排显示的间距
    width=15
).encode(
    x=alt.X('binned_score:Q', title='Score'),
    y=alt.Y('pct:Q', title='Percentage', axis=alt.Axis(format='%')),
    color=alt.Color('label:N', title='Label'),
    # 用xOffset实现同一分箱下不同label的柱子并排
    xOffset='label:N'
).properties(
    width=600,
    height=400
)

关键说明

  • 统一分箱:使用transform_bin对score进行分箱,确保两个类别(True/False)使用完全相同的区间,避免分面导致的轴不一致问题。
  • 百分比计算:
    • 先用transform_joinaggregate计算每个(label, 分箱区间)内的样本数
    • 再计算每个label的总样本数
    • 最后通过transform_calculate得到当前分箱占该label的百分比
  • 并排显示:通过xOffset='label:N'让同一分箱下的不同label柱子并排,配合mark_bar(width)调整柱子间距,替代原有的分面逻辑。
  • Y轴格式化:用axis=alt.Axis(format='%')将Y轴数值直接显示为百分比格式,无需手动转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:47:07