如何消除共享轴双图间隙?用Vega-Altair实现双端柱状图
如何用Altair实现无间隙的双端柱状图?
目标
我希望生成一个“双端”柱状图,展示某指标的获得分数与丢失分数,示例如下:
当前成果
我已写出以下代码:
import altair as alt import pandas as pd source = pd.DataFrame( { "cohort": ["A", "B", "C", "D", "E", "F", "G", "H", "I"], "gained": [28, 55, 43, 91, 81, 53, 19, 87, 52], "missed": [5, 8, 34, 21, 16, 22, 9, 7, 11], } ) up = ( alt.Chart(source) .mark_bar(color="blue") .encode( x=alt.X("cohort:N").axis(labels=False, title=None, ticks=False), y=alt.Y("gained:Q"), ) ) down = ( alt.Chart(source) .mark_bar(color="red") .encode( x=alt.X("cohort:N").axis(labelAngle=0), y=alt.Y("missed:Q", scale=alt.Scale(reverse=True)), ) ) alt.vconcat(up, down).resolve_scale(x="shared")
生成的图表如下:
请问是否有办法消除两个图表之间的间隙?或者是否有其他用Vega-Altair实现双端柱状图的方法?
解决方案
方法1:消除双图拼接的间隙
通过调整拼接参数和图表配置,移除上下图表间的空隙:
import altair as alt import pandas as pd source = pd.DataFrame( { "cohort": ["A", "B", "C", "D", "E", "F", "G", "H", "I"], "gained": [28, 55, 43, 91, 81, 53, 19, 87, 52], "missed": [5, 8, 34, 21, 16, 22, 9, 7, 11], } ) up = ( alt.Chart(source) .mark_bar(color="blue") .encode( x=alt.X("cohort:N").axis(labels=False, title=None, ticks=False), y=alt.Y("gained:Q", axis=alt.Axis(grid=False)), ) .configure_view(strokeWidth=0) # 移除图表边框 ) down = ( alt.Chart(source) .mark_bar(color="red") .encode( x=alt.X("cohort:N").axis(labelAngle=0, title=None), y=alt.Y("missed:Q", scale=alt.Scale(reverse=True), axis=alt.Axis(grid=False)), ) .configure_view(strokeWidth=0) ) alt.vconcat(up, down, spacing=0).resolve_scale(x="shared")
核心调整:
- 设置
alt.vconcat(..., spacing=0)消除图表间的间距 - 用
.configure_view(strokeWidth=0)去掉图表边框 - 隐藏Y轴网格线,让上下柱状图衔接更自然
方法2:单图表实现双端柱状图(更优方案)
将数据转换为长格式,通过正负值在同一图表中实现双向柱状图,天然无间隙:
import altair as alt import pandas as pd source = pd.DataFrame( { "cohort": ["A", "B", "C", "D", "E", "F", "G", "H", "I"], "gained": [28, 55, 43, 91, 81, 53, 19, 87, 52], "missed": [5, 8, 34, 21, 16, 22, 9, 7, 11], } ) # 转换为长格式,将丢失分数设为负值 df_long = source.melt(id_vars="cohort", var_name="type", value_name="score") df_long.loc[df_long["type"] == "missed", "score"] *= -1 chart = alt.Chart(df_long).mark_bar().encode( x=alt.X("cohort:N").axis(labelAngle=0), y=alt.Y("score:Q", title="分数"), color=alt.Color("type:N", scale=alt.Scale(domain=["gained", "missed"], range=["blue", "red"])), tooltip=["cohort", "type", alt.Tooltip("score:Q", format="d")] ).configure_view(strokeWidth=0) chart
该方案优势:
- 单图表结构,逻辑更简洁
- 自动生成图例,区分获得/丢失分数
- 视觉上完全无间隙,效果更统一
内容的提问来源于stack exchange,提问作者dkapitan
相关产品推荐
相关产品推荐

