乡镇街道边界数据下载后先查乡级通名池:1587 个单元、29.3 万平方千米不在正式名录里
乡镇级的 GeoJSON 拿到手,第一件想做的事是把要素按名字列出来对着名录核一遍。真核下去会发现两边永远对不齐,差的那部分往往不是数据错了,而是同一份文件里混着两类东西:正式乡级单元,和行政区划代码里另开一个号池的通名池单元。
这两类要素在字段上几乎看不出差别——都有 name、都有 code、类型 列写的也是"镇"或"乡"。真正的分野藏在 12 位代码的第 7 到第 9 位。
号池的分界线在第 7 位到第 9 位
民政部门的乡级代码是 12 位,前 6 位随区县,第 7 到第 9 位在该县内顺序编号。正式乡级单元的取值区间是 001–399,常见的 100 段是镇、200 段是乡、001 段是街道。第 7 位一旦到 4 以上,性质就变了:400 段是各类农场、林场、垦殖场、牧场、良种场,500 段是开发区、管理区、管委会,600 段是监狱、训练场一类。
这不是哪一份数据源的私人约定,而是代码结构本身给出的信息。判据只有一行:
// 12 位乡级代码:前 6 位区县,第 7-9 位为县内顺序号
// 001-399 => 正式乡级;400 及以上 => 农林场/开发区等通名池单元
function poolOf(code) {
const mid = String(code ?? '').slice(6, 9);
if (!/^\d{3}$/.test(mid)) return 'bad';
return mid >= '400' ? 'pool' : 'formal';
}
把 32 个省级聚合文件全量扫一遍,共 41470 个乡镇级要素。按上面这一行判下来,落在通名池里的有 1587 个,对应面积 293066 平方千米,占全国县级合计面积的 3.09%。它们分布在 461 个区县里。
通名池吃掉的比例,按县看是断崖式的
平均值没有意义。同一个池子在不同县里的分量,能从零一路占到九成以上。
| 省份 | 区县 | 要素总数 | 通名池要素 | 通名池面积占比 |
|---|---|---|---|---|
| 浙江 | 桐庐县 | 14 | 14 | 100.0% |
| 黑龙江 | 岭东区 | 3 | 2 | 95.3% |
| 黑龙江 | 爱辉区 | 24 | 13 | 94.7% |
| 黑龙江 | 萝北县 | 16 | 8 | 86.6% |
| 新疆 | 阿瓦提县 | 13 | 5 | 86.0% |
| 黑龙江 | 五大连池市 | 33 | 22 | 84.4% |
| 新疆 | 库车市 | 16 | 14 | 76.8% |
| 黑龙江 | 虎林市 | 18 | 7 | 74.9% |
| 新疆 | 沙雅县 | 16 | 5 | 74.5% |
| 江西 | 青山湖区 | 11 | 5 | 28.6% |
黑龙江爱辉区的明细最能说明问题。这个区一共 24 个要素,其中正式乡级只有 11 个——西岗子镇 72.05 平方千米、瑷珲镇 196.74 平方千米、新生鄂伦春族乡 0.85 平方千米。11 个正式单元加起来只占全区面积的 5.3%。另外 13 个是林场与农场:大岭林场一个就 5210.18 平方千米,占全区 40.81%;滨南林场 1176.47、锦河农场 1591.79、江防林场 815.23。把这份文件按"有多少个乡镇"去统计,会得到 24;按正式名录去对,只能对上 11。差出来的 13 个不是脏数据,是森工与农垦系统的实体,在正式民政名录里本来就没有对应条目。
江西永修县的 20 个要素同理,比例更温和但结构一样:14 个正式乡级里,吴城镇 372.77 平方千米最大;6 个通名池单元里,云山企业集团 292.44、恒丰企业集团 81.80、八角岭垦殖场 14.16、永丰垦殖场 35.68,再加一个 501 段的江益镇 81.05。这 6 个加起来占全县 24.6%。
表格统计与地图着色,各按什么口径取
口径选择取决于下游要干什么,两种都成立,但要一致。
做统计台账、跟正式名录对账,应当只取正式段。上面这 461 个区县里,如果把通名池单元一并计入"乡镇个数",会系统性多出一截——爱辉区多 13 个,永修县多 6 个,桐庐县甚至一个正式单元都没有。
做地图着色或面积汇总,反而不能剔除。爱辉区逐要素着色时若把 13 个林场农场归到"未匹配"再丢弃,全区四成面积会直接空在图上,看上去像几何缺失。正确做法是保留几何、把池内单元用另一套色值或虚线边界区分开,并在图例里单列一行。
这里有个容易踩空的边界:判据用的是代码第 7–9 位,而 类型 列不可靠。同一批数据里出现过一个 501 段的要素,类型 写的是"镇"——名字叫江益镇,代码却落在开发区段。反过来的例子也有:一个 400 段的要素挂着"乡"的类型标注。同一条规则要能同时接住这两种情况,就不能依赖 类型 列做分流依据,只能看代码位。
代码位本身也可能缺。全量里有 319 个要素的第 7–9 位不是纯数字或整列为空,集中在少数几份文件里;这部分既不能判成正式也不能判成池,单独归入"待补"队列,不要默认塞进任何一边。另有个别要素的 name 是 0 或纯数字这类无量值,山西、甘肃两省的这类要素分别覆盖了各自省面积的 21.42% 与 8.68%,处理时按"名称不可用但几何有效"对待:几何照常参与着色与面积统计,名称列留给后续按代码回填。
落成流程时的顺序
把上面的判断串起来,一次清洗大概是这个次序:
1. 先按代码位分池,不要先按名称或类型过滤。分完池再谈别的,能避免把林场当成脏数据删掉。 2. 名称列单跑一遍可用性判定。空值、0、纯数字、含"未命名"的一律标为不可用;含括号注释的(如"林东西城街道(办事处)")先剥掉括号段再比名,全量这类名称有 120 个。 3. 同县同名单独核对。全量有 467 个区县存在同县内重名,多出 883 个要素,其中一部分是历史遗留、一部分是通名池单元与正式单元撞名——宜丰县一个县里"澄塘镇"这个名字出现在 7 个要素上,覆盖 145.99 与 1.47 平方千米两种尺度,靠代码位分池后它们自然分到了两边。 4. 逐县做面积闭环。上面抽查的四个县里,宜丰县、吉水县、泰顺县的要素面积合计与公开县面积分别差 0.1%、0.2%、0.5%,说明分池分对了;永登县差了 4.0%,就该回头看这个县的县级边界与本县要素之间是不是有缺口,而不是急着改乡级数据。
这套判据的价值集中在数据入库与建模环节。换个场景,如果目的只是把某个市或某个县摆进汇报材料里当底图,重跑一遍分池其实没必要——模板选购页 里按省市逐级备了可编辑底图,单份 ¥4.99,预览免费,农林场那类单元与正式乡级已经分色排好,选中哪块改哪块就行。
上面这批数值来自某一次聚合版本的快照,换一版源会有浮动。真正可迁移的是判据形式:它只依赖 12 位乡级代码的内部结构,与文件出自哪个数据源没有关系,因此 GeoJSON下载 得到的文件只要带这一列代码,同一段逻辑可以直接套用。把分池与名称可用性两步写进流水线的固定节点,比每次开工临时决定哪些要素算数、哪些要素剔掉要稳得多。