如何基于Pandas DataFrame创建印尼Scattermapbox分层地图?
解决印尼区域Scattermapbox着色问题:DataFrame生成图层或独立文件方案
首先帮你修正下代码里的小错误:你获取区域名称的循环里,变量用了region但内部写了state['properties']['name'],这会导致NameError,得改成region['properties']['name']。接下来分两种方案解决你的需求:
一、直接用Pandas DataFrame生成图层字典(推荐)
这个方案不需要生成独立文件,直接把GeoJSON数据和你的统计DataFrame合并,动态生成每个区域的图层配置,根据统计值着色。
步骤说明:
- 加载印尼GeoJSON数据,提取每个区域的feature和名称
- 准备你的统计数据(比如人口、GDP,假设是一个包含
region_name和对应数值的DataFrame) - 将GeoJSON的feature和统计数据按区域名称合并
- 遍历合并后的数据,生成每个区域的图层字典,用颜色映射对应统计值
修正后的完整代码:
import pandas as pd import plotly import plotly.graph_objs as go from plotly.colors import sequential # 1. 加载印尼GeoJSON数据 geojson_url = 'https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/indonesia-edit.geojson' id_geojson = pd.read_json(geojson_url) # 提取区域名称和对应的feature region_features = [] region_names = [] for feature in id_geojson['features']: region_names.append(feature['properties']['name']) region_features.append(feature) # 2. 模拟你的统计数据(替换成你实际的DataFrame) stats_df = pd.DataFrame({ 'region_name': region_names, 'population': [12000000, 9500000, 8200000] + [5000000]*(len(region_names)-3) # 示例数据 }) # 3. 合并feature和统计数据 regions_data = pd.DataFrame({ 'name': region_names, 'feature': region_features }).merge(stats_df, left_on='name', right_on='region_name') # 4. 生成颜色映射(根据population值) min_pop = regions_data['population'].min() max_pop = regions_data['population'].max() color_scale = sequential.Reds def get_color(value): # 计算数值在颜色刻度中的位置 idx = int((value - min_pop)/(max_pop - min_pop) * (len(color_scale)-1)) return color_scale[idx] # 5. 生成Scattermapbox的layers map_layers = [] for _, row in regions_data.iterrows(): layer = dict( sourcetype='geojson', source={'type': 'FeatureCollection', 'features': [row['feature']]}, type='fill', color=get_color(row['population']), opacity=0.7, # 可选:添加hover信息 hoverinfo='text', text=f"{row['name']}: {row['population']:,}" ) map_layers.append(layer) # 6. 构建地图布局和数据 mapbox_access_token = '你的Mapbox密钥' data = [go.Scattermapbox( lat=[], lon=[], mode='markers', marker=dict(size=0) # 隐藏默认标记,只显示区域填充 )] layout = go.Layout( height=900, autosize=True, showlegend=False, hovermode='closest', mapbox=dict( layers=map_layers, accesstoken=mapbox_access_token, bearing=0, center=dict(lat=0.7893, lon=113.9213), pitch=0, zoom=4.5, style='light' ) ) fig = go.Figure(data=data, layout=layout) plotly.offline.plot(fig, filename='Chloropleth_Province_Population.html')
二、生成各区域独立GeoJSON文件(备选方案)
如果还是需要生成独立文件,修正你之前的create_region_files函数:问题在于你直接把DataFrame的行转成JSON,但实际上每个区域的GeoJSON需要是完整的FeatureCollection格式,而且遍历方式不对。
修正后的函数代码:
import json import os def create_region_files(): # 创建保存目录 save_dir = 'C:\\Users\\nicho\\Desktop\\Waste Management\\Map_Maker\\ID_regions' os.makedirs(save_dir, exist_ok=True) # 遍历每个feature for feature in id_geojson['features']: region_name = feature['properties']['name'] # 生成完整的GeoJSON格式 region_geojson = { "type": "FeatureCollection", "features": [feature] } # 保存文件(注意处理特殊字符,避免文件名错误) filename = f"{region_name.replace('/', '_')}.json" file_path = os.path.join(save_dir, filename) with open(file_path, 'w', encoding='utf-8') as f: json.dump(region_geojson, f, ensure_ascii=False, indent=2) # 调用函数生成文件 create_region_files()
这样生成的每个文件都是标准的GeoJSON,可以直接作为Scattermapbox的layer source使用。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

