Altair中拼接地图时transform_calculate关联类别图例排序异常修复
修复Altair拼接地图后图例排序混乱的问题
我尝试将多张通过字符串字典标注的分级统计图(choropleth)拼接,它们共享图例。但拼接后图例排序混乱,原本的首个类别变成了最后一个,单独绘制单张地图时代码运行正常。

原始代码
import altair as alt import geopandas as gpd import pickle import requests resp = requests.get("https://raw.githubusercontent.com/ccsuehara/cfi/main/mapping.pickle") mapping = pickle.loads(resp.content) srcs = gpd.read_file("https://raw.githubusercontent.com/ccsuehara/cfi/main/example.geojson") base = alt.Chart(srcs).mark_geoshape().properties( width=400, height=400 ).project( type='mercator' ) g_ = alt.concat( base.encode( color=alt.Color( 'disp_2010:N', scale=alt.Scale(scheme='greens'), title = "% Change (winsor)", sort=alt.EncodingSortField('class_2010_win', order='ascending') ), ).transform_filter( 'isValid(datum.class_2010_win)' ).transform_calculate( disp_2010=f"{mapping}[datum.class_2010_win]" ).properties( title="Δ 2005 - 2010(%)" ) | base.encode( color=alt.Color( 'disp_2015:N', scale=alt.Scale(scheme='greens'), title = "% Change (winsor)", #sort=alt.EncodingSortField('class_2010_win', order='ascending') ), ).transform_filter( 'isValid(datum.class_2015_win)' ).transform_calculate( disp_2015=f"{mapping}[datum.class_2015_win]", ).properties( title="Δ 2010 - 2015(%)" ) ) g_
问题原因
拼接图表共享图例时,Altair会合并两个图表的排序规则,但第二个图表未指定排序逻辑,导致整体排序被打乱。同时,transform_calculate生成的离散字段排序依赖各自的数值类字段(class_2010_win和class_2015_win),拼接时规则冲突引发排序异常。
修复方案
方案1:统一两个图表的排序依据
给第二个图表添加与第一个图表逻辑一致的排序参数,基于各自的数值类别字段:
# 修改第二个图表的color编码 color=alt.Color( 'disp_2015:N', scale=alt.Scale(scheme='greens'), title = "% Change (winsor)", sort=alt.EncodingSortField('class_2015_win', order='ascending') ),
方案2:提前定义固定排序顺序(更稳定)
直接从mapping字典中提取固定的类别顺序,作为两个图表的排序基准,彻底避免字段依赖的不确定性:
# 从mapping字典获取按键排序后的标签列表 sorted_labels = [v for k, v in sorted(mapping.items())] # 在两个图表的color编码中使用该固定顺序 color=alt.Color( 'disp_2010:N', scale=alt.Scale(scheme='greens', domain=sorted_labels), title = "% Change (winsor)", sort=sorted_labels ),
完整修复代码
import altair as alt import geopandas as gpd import pickle import requests resp = requests.get("https://raw.githubusercontent.com/ccsuehara/cfi/main/mapping.pickle") mapping = pickle.loads(resp.content) # 提前生成固定排序的类别标签 sorted_labels = [v for k, v in sorted(mapping.items())] srcs = gpd.read_file("https://raw.githubusercontent.com/ccsuehara/cfi/main/example.geojson") base = alt.Chart(srcs).mark_geoshape().properties( width=400, height=400 ).project( type='mercator' ) g_ = alt.concat( base.encode( color=alt.Color( 'disp_2010:N', scale=alt.Scale(scheme='greens', domain=sorted_labels), title = "% Change (winsor)", sort=sorted_labels ), ).transform_filter( 'isValid(datum.class_2010_win)' ).transform_calculate( disp_2010=f"{mapping}[datum.class_2010_win]" ).properties( title="Δ 2005 - 2010(%)" ) | base.encode( color=alt.Color( 'disp_2015:N', scale=alt.Scale(scheme='greens', domain=sorted_labels), title = "% Change (winsor)", sort=sorted_labels ), ).transform_filter( 'isValid(datum.class_2015_win)' ).transform_calculate( disp_2015=f"{mapping}[datum.class_2015_win]", ).properties( title="Δ 2010 - 2015(%)" ) ) g_
内容的提问来源于stack exchange,提问作者Carla S.
相关产品推荐
相关产品推荐

