Altair transform_lookup绘制丹麦市政犯罪热力图失败求助
问题
我尝试绘制丹麦各市政区域的犯罪热力图,用颜色编码对应区域的犯罪总数。数据按时间周期和犯罪类型拆分,每个市政有多条记录,但仅对应一条几何数据。我希望通过label_dk键对GeoPandas数据框中的geometry字段执行transform_lookup操作,但地图始终无法渲染。
我本可合并数据框,但为节省空间避免重复存储几何数据(实际数据约3万条,合并后GeoJSON达647000KB导致地图无法渲染),同时需基于时间和犯罪类型做数据切片分析,因此想采用lookup方案。请问为何transform_lookup无法生效?
数据样例
几何数据(99行)
label_dk geometry 0 Aabenraa MULTIPOLYGON Z (((9.51215 54.85672 -999.00000,... 1 Aalborg MULTIPOLYGON Z (((9.84688 57.04365 -999.00000,... 2 Aarhus POLYGON Z ((9.99682 56.17872 -999.00000, 9.990... 3 Albertslund POLYGON Z ((12.35234 55.70461 -999.00000, 12.3... 4 Allerød POLYGON Z ((12.31845 55.88305 -999.00000, 12.3... .. ... ... 94 Vejle POLYGON Z ((9.11714 55.76669 -999.00000, 9.100... 95 Vesthimmerlands MULTIPOLYGON Z (((9.17798 56.91745 -999.00000,... 96 Viborg POLYGON Z ((9.29501 56.59336 -999.00000, 9.297... 97 Vordingborg MULTIPOLYGON Z (((12.04479 54.95566 -999.00000... 98 Ærø MULTIPOLYGON Z (((10.43467 54.87952 -999.00000...
犯罪数据(792行)
tid offence label_dk Anmeldte forbrydelser 0 2021K1 Seksualforbrydelser i alt København 133 1 2021K1 Voldsforbrydelser i alt København 900 2 2021K2 Seksualforbrydelser i alt København 244 3 2021K2 Voldsforbrydelser i alt København 996 4 2021K3 Seksualforbrydelser i alt København 174 .. ... ... ... ... 787 2021K2 Voldsforbrydelser i alt Aalborg 178 788 2021K3 Seksualforbrydelser i alt Aalborg 53 789 2021K3 Voldsforbrydelser i alt Aalborg 185 790 2021K4 Seksualforbrydelser i alt Aalborg 43 791 2021K4 Voldsforbrydelser i alt Aalborg 205
代码
import altair as alt import geopandas as gpd import pandas as pd import altair_viewer alt.data_transformers.enable('data_server') path = "data/small_few_umbrella_terms_crimes_2021.csv" df = pd.read_csv(path,encoding="utf_8",index_col='Unnamed: 0') geometry = gpd.read_file("data_with_geo/geometry.geojson") map_chart = alt.Chart(df).mark_geoshape( ).transform_aggregate( crime='sum(Anmeldte forbrydelser)', groupby=["label_dk"] ).transform_lookup( lookup='label_dk', from_=alt.LookupData(geometry, 'label_dk', ['geometry']) ).encode( color=alt.Color( "crime:Q", scale=alt.Scale( scheme='viridis') ) ) altair_viewer.show(map_chart)
解决方案
你的transform_lookup失效主要有两个核心原因,对应修复方法如下:
1. LookupData无法直接解析GeoPandas的地理对象
Altair的alt.LookupData无法识别GeoPandas数据框中geometry字段的地理空间对象类型,它需要序列化后的GeoJSON格式数据才能正确渲染图形。
修复方法:
将GeoDataFrame转换为普通Pandas数据框,并把geometry字段转为GeoJSON结构:
# 转换坐标系为Altair默认的WGS84(EPSG:4326),再将geometry转为GeoJSON geometry_df = geometry.to_crs(epsg=4326).assign( geometry=lambda x: x.geometry.apply(lambda geom: geom.__geo_interface__) )
2. 需确保匹配键完全一致
聚合后的label_dk与几何数据中的label_dk必须完全匹配(包括丹麦语特殊字符、大小写),否则会出现匹配失败,导致无几何数据可渲染。
完整修复代码
import altair as alt import geopandas as gpd import pandas as pd import altair_viewer alt.data_transformers.enable('data_server') path = "data/small_few_umbrella_terms_crimes_2021.csv" df = pd.read_csv(path, encoding="utf_8", index_col='Unnamed: 0') # 读取并转换几何数据格式 geometry = gpd.read_file("data_with_geo/geometry.geojson") geometry_df = geometry.to_crs(epsg=4326).assign( geometry=lambda x: x.geometry.apply(lambda g: g.__geo_interface__) ) map_chart = alt.Chart(df).mark_geoshape( ).transform_aggregate( crime='sum(Anmeldte forbrydelser)', groupby=["label_dk"] ).transform_lookup( lookup='label_dk', from_=alt.LookupData(geometry_df, 'label_dk', ['geometry']) ).encode( color=alt.Color("crime:Q", scale=alt.Scale(scheme='viridis')), tooltip=['label_dk:N', 'crime:Q'] # 可选:添加悬浮显示信息 ).properties( width=600, height=600 ) altair_viewer.show(map_chart)
额外优化建议
- 如果要支持时间和犯罪类型的切片分析,可以添加交互选择器,结合
transform_filter实现动态筛选:# 时间周期选择器示例 tid_selector = alt.binding_select(options=df['tid'].unique()) tid_select = alt.selection_single(fields=['tid'], bind=tid_selector, name='选择时间周期') map_chart = alt.Chart(df).mark_geoshape( ).add_selection(tid_select ).transform_filter(tid_select ).transform_aggregate( crime='sum(Anmeldte forbrydelser)', groupby=["label_dk"] ).transform_lookup( lookup='label_dk', from_=alt.LookupData(geometry_df, 'label_dk', ['geometry']) ).encode( color=alt.Color("crime:Q", scale=alt.Scale(scheme='viridis')), tooltip=['label_dk:N', 'crime:Q'] ) - 始终确保几何数据使用EPSG:4326坐标系,这是Altair地理图形的默认坐标系,避免出现位置偏移或不渲染问题。
内容的提问来源于stack exchange,提问作者AsgerUR
相关产品推荐
相关产品推荐

