GeoJSONcn
GeoJSONcn / 技术专栏 / 分级设色地图实战:用行政区划代码…

分级设色地图实战:用行政区划代码把统计数据接到 GeoJSON 上

发布于 2026-07-24 · GeoJSONcn 技术团队 · 阅读约 10 分钟

--- title: 分级设色地图实战:用行政区划代码把统计数据接到 GeoJSON 上 ---

分级设色地图(Choropleth)是最常见的专题地图:每个行政区按数值深浅填色,人口、GDP、销量的地域分布一眼就能看出来。做这种图需要两份数据,一份行政区边界 GeoJSON,一份业务统计表。麻烦在于怎么把两份数据正确地"接"起来。这篇讲清楚 join 的正确姿势,附能直接跑的 Leaflet 代码。

先说关键原则:用区划代码 join,别用名字

最容易踩的坑是拿"区县名"当主键去关联数据。中国的区县重名不少:

名称区划代码所属
朝阳区110105北京市
朝阳区220104吉林省长春市
鼓楼区320106江苏省南京市
鼓楼区350102福建省福州市
鼓楼区410204河南省开封市

用名字 join,一个"朝阳区"的数据会同时染到北京和长春两块面上,结果直接错。正确做法是用民政部发布的 6 位行政区划代码(adcode)当唯一主键:GeoJSON 的 properties 里带 adcode 字段,业务表也带 adcode 列,两边一一对应。properties 的结构不熟的话,可以回顾 GeoJSON 到底是什么。

数据 join 代码

先把统计表(CSV 解析后的数组)转成 Map,渲染时按 adcode 查值。查 Map 是 O(1),比每次 find 遍历数组快得多:

// 业务数据:[{ adcode: "110105", value: 345.2 }, ...]
const valueMap = new Map(rows.map(r => [String(r.adcode), r.value]));

// 把数值写进 GeoJSON 的 properties,方便后续统一取用
geojson.features.forEach(f => {
  const code = String(f.properties.adcode);
  f.properties.value = valueMap.get(code) ?? null;   // 缺数据的区置 null
});

两个细节。一是 adcode 统一转字符串再比对,不然 110105(数字)和 "110105"(字符串)对不上;二是缺数据的区置 null 而不是 0——"没有数据"和"数值为零"在地图上该是两种颜色。

Leaflet 着色

function getColor(v) {
  if (v === null) return '#eeeeee';        // 无数据:灰色
  return v > 500 ? '#08306b' :
         v > 300 ? '#2171b5' :
         v > 150 ? '#6baed6' :
         v > 50  ? '#c6dbef' : '#f7fbff';
}

L.geoJSON(geojson, {
  style: f => ({
    fillColor: getColor(f.properties.value),
    fillOpacity: 0.75,
    color: '#ffffff',    // 描边用白色,分区更清楚
    weight: 1
  }),
  onEachFeature: (f, layer) => {
    layer.bindTooltip(`${f.properties.name}:${f.properties.value ?? '无数据'}`);
  }
}).addTo(map);

坐标系还是老规矩:边界数据统一用 WGS84 存储,叠加到不同底图前先确认是否需要偏移处理,细节见 坐标系那篇。

分级方法怎么选

getColor 里的断点(50/150/300/500)不是随手写的。分级方法直接决定这张地图"讲什么故事":

分级方法原理适用场景缺点
等间距(最大值-最小值)/组数数据均匀分布有极值时大部分区挤在一档
分位数每档区县数量相同强调排名对比数值差异被隐藏
自然断点Jenks 算法找聚类间隙多数真实数据计算稍复杂,断点不整
手动分级按业务含义定断点有行业标准阈值时依赖领域知识

人口、GDP 这类右偏分布的数据,用等间距几乎必翻车:北京上海把上限拉高,全国大部分区县落在最浅一档,整张图白茫茫一片。这种情况优先试分位数或自然断点。

性能提醒

全国区县级边界一次性加载体积不小,直接渲染 2800 多个面可能明显卡顿。两个办法:一是先做 Douglas-Peucker 顶点抽稀,分级设色关注的是"哪块什么颜色",边界精度可以适当放宽;二是换 TopoJSON 传输,共享边只存一次,到浏览器再还原。

省、市、区县三级的边界 GeoJSON 数据(含 adcode 字段),可以在 GeoJSONcn 主站 按行政区划直接检索预览。