GeoJSONcn
GeoJSONcn / 技术专栏 / 全国村级GeoJSON键值核对:…

全国村级GeoJSON键值核对:空心属性、旧码残留与层级缺环怎么回写

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

把全国村级geojson数据下载回来做统计,最容易被跳过的一步是键值核对。拿到文件先看形状对不对,形状对了就开工,等挂到乡镇、区县上汇总才发现对不齐——面在图上位置没错,码在现行区划里查不到。省级、区县级数据里这类问题少见,越往村级越密集:村级边界多来自测绘与规划系统的作业底图,编码口径与民政部门发布的行政区划代码本就是两套。这篇用一份省级村界文件实测,讲清空心属性、旧码残留、层级缺环三类病症的识别与回写。

病症一:属性字段在,里面是空的

打开文件先别急着画图,把 properties 抽出来看一眼。一份 8021 个要素的省级村界样本,字段七项齐全,看着挺规范:

{"省": "北京", "市": "", "区县": "", "乡镇": "",
 "村名": "于家台村", "村级码": "110228002214", "类型": "行政村"}

市、区县、乡镇 三个字段全是空字符串,全文件无一例外。这种结构俗称空心属性:字段名留着位置,值从没填过。作业底图本身按行政代码分级组织,层级信息藏在码里,不需要再冗余一份文字字段,这些键就成了占位符。

画图不受影响,做统计立刻绊住。按区县汇总村数没有分组键,按乡镇分级着色也找不到可用字段。出路是从码里还原层级,前提是码本身可信。

病症二:码是旧码,现行区划里查无此码

拿样本里的 110228 去现行代码库检索,结果是零条命中。这不是数据出错,而是这个县级码已经被替换过:样本中它的 468 个要素,对应的是今天编码为 110118 的区。类似情况在同批文件里占到了要素总数的 16.2%。

乡镇一级更明显。以该市某中心城区为例,民政部门公布的乡级单位共 15 个,码从 110102001 到 110102020;村界文件里同区的前缀只有 7 个,且编号排布与权威序列并不对应。整批文件里,前缀无法与现行乡级码匹配的要素占到 48.5%。

这里最要紧的一句话是:旧码与现行码之间不存在可推算的映射规律。 代码库里的编号是稀疏的,有号段没有实体在册,编号顺序与单位名称、地理位置都没有稳定关系。指望按数字大小插号、按规律补出缺失号,方向从开头就错了。能对上的只有人工维护的对照表,或者名称加空间范围做间接判定,两者都得逐个核。

核对项样本实测后果处理方向
市/区县/乡镇字段100% 为空字符串无法按层级分组汇总从村级码前缀还原
县码非现行(16.2%)110228 已并入 110118按县 join 直接漏掉换权威码或建对照表
乡镇码非现行(48.5%)权威 15 个 vs 文件 7 个前缀乡镇级统计错位名称+空间双重判定
街坊类要素占比 45.4%与行政村混在同一层按类型分层,别合并计数

病症三:层级缺环,中间一层落空

第三个坑比前两个隐蔽。部分省级文件来自城区精细测绘成果,图层切分到街坊、地块一级,命名形如「什刹海街道014街坊」,类型却统一标成「行政村」。这份样本里有 45.4% 的要素属于这一类。

把它们和真正的行政村并进同一张表汇总,数字会大幅虚高。更要紧的是乡镇这一环会落空:街坊图层按作业分区组织,编码前缀指向的分区不等同于行政区划中的乡镇街道。另一份直辖市样本里,村级码 字段整列为空,替代信息是五位的 STREETCODE 加 BLOCK_CODE,五位街道码共 239 个,该市权威乡级单位是 216 个——多出的一截正是作业分区与行政建制的差额。

处理办法是先分层再合并。按 类型 字段把街坊类与行政村类分开,各自统计、各自出图;要合并到乡镇一级,只能靠名称或空间归属去挂,不能沿用文件自带的编码前缀。

回写规范:别直接覆盖原始码

识别出问题就要回写,回写的第一条纪律是保留原始码。供应商给的码直接改掉,后续版本比对、问题回溯都没了依据。稳妥做法是新增两列,原值原样留着。

function reKey(rows, alive) {
  return rows.map(r => {
    const raw = String(r.村级码 || '');
    const town9 = raw.slice(0, 9);
    const hit = alive.get(town9);
    return {
      ...r,
      原始码: raw,
      县码: hit ? hit.县码 : '',
      乡镇码: hit ? town9 : '',
      乡镇名: hit ? hit.乡镇名 : '',
      归属状态: hit ? 'matched' : 'orphan',
      类型分层: /街坊|地块|小区/.test(r.村名) ? 'block' : 'village'
    };
  });
}

两处细节值得盯住。命不中现行码的要素别丢弃,标成 orphan 单独出一份清单:这批东西里有的是真撤并,有的是作业分区,混在一起删掉会丢真数据。分层判定在回写阶段做一次,别等出图时再判断。

回写是否收工,看面积与要素数的双向闭环:按乡镇聚合的村面合并一次,并集面积与该乡镇面边界面积对比,偏差超阈值就说明有村挂错地方或碎块未归拢。这一步不做,键值核对只完成前半程。

这类核对是慢活,也正因如此值得把结果沉淀成数据产品。全国省市区县区划边界数据下载的场景里,用户拿到的是成品边界;全国省市区县geojson数据下载之后能不能直接喂进统计脚本,取决于中间有没有人把键值这层做干净。统计与民政部门逐年调整代码,增量核对每年都省不掉,把它做成脚本加人工复核的固定环节,比临时救火划算。顺带提一句,GeoJSON下载回来第一步就该跑一遍键值体检,而不是等统计结果对不上再回头查。

键值做干净之后,边界数据的可用性会上一个台阶。若下一步用途是把省、市、区县轮廓铺进汇报版面,需要逐块改色的可编辑底图可到 PPT 地图模板选购页 按省按市下钻挑,先看预览图确认形状与范围再决定下载哪一份;拿它当边界核对的可视化参照,比在命令行里比对码值直观。

一句话收束:村级边界能不能用,形状只占一半,另一半是键值。空心属性、旧码残留、层级缺环这三样在省级文件里不显眼,到村级却成了常态,也没有靠公式补齐的捷径。把原始码留档、孤儿要素单列、分层判定提前,再用面积闭环验一次,这套动作固定下来,每年区划调整带来的返工量会小很多。