Matplotlib contourf填充等高线图转GeoJSON并Folium展示异常
解决Matplotlib填充等高线转GeoJSON并在Folium中正确显示的问题
在Google Colab环境中使用plt.contourf生成填充等高线图后,将其转换为GeoJSON导入Folium时出现多边形构建错误,以下是问题分析和修正方案:
问题根源
- 层级与Collections不匹配:
np.linspace生成11个等高线值,对应10个填充区间,但contourf_plot.collections的数量是10个,直接zip会导致层级对应错误。 - 路径处理不当:Matplotlib的
Path可能包含带内环的复杂多边形,直接取vertices无法区分内外环,导致GeoJSON多边形结构错误。 - 冗余的坐标闭合操作:
path.to_polygons()已自动闭合多边形,手动重复起点会导致GeoJSON格式异常。
修正后的代码
import numpy as np import folium import matplotlib.pyplot as plt from matplotlib.colors import to_hex, Normalize import requests from io import BytesIO import xarray as xr # 下载并读取NetCDF数据 url = "https://www.star.nesdis.noaa.gov/socd/mecb/sar/AKDEMO_products/APL_winds/tropical/2024/SH052024_BELAL/STAR_SAR_20240116013937_SH052024_05S_MERGED_FIX_3km.nc" response = requests.get(url) dataset = xr.open_dataset(BytesIO(response.content)) sar_wind = dataset['sar_wind'].values latitude = dataset['latitude'].values longitude = dataset['longitude'].values # 生成等高线层级(11个值对应10个填充区间) iso_values_filled = np.linspace(np.min(sar_wind), np.max(sar_wind), 11) contourf_plot = plt.contourf(longitude, latitude, sar_wind, levels=iso_values_filled, cmap='viridis') # 转换为GeoJSON FeatureCollection geojson_data_polygon = {"type": "FeatureCollection", "features": []} norm = Normalize(vmin=iso_values_filled.min(), vmax=iso_values_filled.max()) # 遍历每个填充区间(对应collection),使用区间的中间值映射颜色 for idx, collection in enumerate(contourf_plot.collections): # 取当前区间的上下限,计算中间值作为颜色映射基准 level_min = iso_values_filled[idx] level_max = iso_values_filled[idx+1] level_mid = (level_min + level_max) / 2 color_hex = to_hex(plt.cm.viridis(norm(level_mid))) for path in collection.get_paths(): # 将路径分解为多边形(自动处理内外环) polygons = path.to_polygons() if not polygons: continue # GeoJSON Polygon格式:外环+多个内环 coordinates = [polygon.tolist() for polygon in polygons] geojson_data_polygon["features"].append({ "type": "Feature", "geometry": { "type": "Polygon", "coordinates": coordinates }, "properties": { "level_min": level_min, "level_max": level_max, "color": color_hex } }) # 创建Folium地图并添加GeoJSON图层 center_lat, center_lon = np.mean(latitude), np.mean(longitude) mymap_polygon = folium.Map(location=[center_lat, center_lon], zoom_start=8) folium.GeoJson( geojson_data_polygon, style_function=lambda feature: { 'fillColor': feature['properties']['color'], 'color': 'none', # 隐藏边界线,避免重叠混乱 'fillOpacity': 0.7 } ).add_to(mymap_polygon) # 显示地图 mymap_polygon
关键修正说明
- 层级匹配:通过
enumerate遍历collections,对应每个填充区间的上下限,用中间值映射颜色,确保层级与颜色对应准确。 - 路径分解:使用
path.to_polygons()将复杂路径拆分为外环和内环,符合GeoJSON Polygon的结构要求(外环在前,内环在后)。 - 优化样式:将边界线设为
'none',避免多个层级的边界线重叠导致视觉混乱。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

