3. 点数据清洗实战

环境监测点数据是环境质量评价、污染溯源和空间插值的基础。无论是空气质量自动监测站,还是地表水、地下水采样点,在进入GIS分析或数据库之前,往往来自不同年代、不同单位、不同采集方式,存在坐标系统不统一、点位重复、坐标偏移、属性缺失和格式混乱等问题。本节以一批假想的监测点数据为例,完整走一遍点数据清洗的关键环节,重点讲清每一步“判断什么、怎么处理、处理到什么程度算合格”。

一、先看清数据:字段结构与问题诊断

假设我们拿到一份名为 monitor_points.csv 的点位清单,包含空气质量监测点和水质采样点两类对象,主要字段有:点位编号 site_id、点位名称 site_name、类型 site_type、经度 lon、纬度 lat、坐标系统 crs、监测指标 parameter、所属行政区 district、建站年份 year。示例数据中,部分点位 crs 标注为 WGS84,部分标注为 CGCS2000,还有几条为 GCJ02;个别点位经纬度明显落在研究区之外;少数点位 district 为空;点位名称存在“XX站”“XX监测站”“XX站(空气)”等多种写法。这些问题正是清洗要解决的对象。

诊断阶段建议先做三件事:一是统计各字段的空值率与取值分布,二是把点位按经纬度快速投到地图上目视检查,三是核对 site_id 是否唯一。目视检查非常关键,很多异常坐标在表格里看不出来,一上图就暴露为“飞点”。

二、坐标系统一:先明确目标坐标系

坐标系统一不是把所有点“改成同一个标签”,而是把坐标数值真正转换到同一参考框架下。本课程约定:分析底图采用 CGCS2000 地理坐标系,单位为度。因此处理原则是:CGCS2000 点位保持不变;WGS84 点位在一般环境监测精度要求下可视为与 CGCS2000 基本一致,直接沿用并统一标注;GCJ02(火星坐标)点位必须做偏移纠正,不能简单改标签。

GCJ02 转 WGS84 没有精确解析解,工程上常用迭代逼近。下面给出一个可运行的 Python 示例,采用公开的坐标偏移算法思路,迭代若干次使结果收敛(示例参数与结果仅用于教学演示):

import math

a = 6378245.0
ee = 0.00669342162296594323

def _transform_lat(x, y):
    ret = -100.0 + 2.0*x + 3.0*y + 0.2*y*y + 0.1*x*y + 0.2*math.sqrt(abs(x))
    ret += (20.0*math.sin(6.0*x*math.pi) + 20.0*math.sin(2.0*x*math.pi)) * 2.0/3.0
    ret += (20.0*math.sin(y*math.pi) + 40.0*math.sin(y/3.0*math.pi)) * 2.0/3.0
    ret += (160.0*math.sin(y/12.0*math.pi) + 320*math.sin(y*math.pi/30.0)) * 2.0/3.0
    return ret

def _transform_lon(x, y):
    ret = 300.0 + x + 2.0*y + 0.1*x*x + 0.1*x*y + 0.1*math.sqrt(abs(x))
    ret += (20.0*math.sin(6.0*x*math.pi) + 20.0*math.sin(2.0*x*math.pi)) * 2.0/3.0
    ret += (20.0*math.sin(x*math.pi) + 40.0*math.sin(x/3.0*math.pi)) * 2.0/3.0
    ret += (150.0*math.sin(x/12.0*math.pi) + 300.0*math.sin(x/30.0*math.pi)) * 2.0/3.0
    return ret

def gcj02_to_wgs84(lon, lat):
    dlon, dlat = lon, lat
    for _ in range(10):
        tlat = _transform_lat(dlon - 105.0, dlat - 35.0)
        tlon = _transform_lon(dlon - 105.0, dlat - 35.0)
        radlat = lat / 180.0 * math.pi
        magic = 1 - ee * math.sin(radlat)**2
        sqrtmagic = math.sqrt(magic)
        tlat = (tlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi)
        tlon = (tlon * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi)
        dlat = lat - tlat
        dlon = lon - tlon
    return round(dlon, 6), round(dlat, 6)

转换后应保留原始坐标字段(如 lon_raw、lat_raw)以便回溯,并新增 crs_std 字段统一写为 CGCS2000。判断转换是否合理的经验方法是:转换前后位移量一般在数百米量级,若某点位移达到数公里,说明原始标注的坐标系可能本身就错了,需要回到数据源核实。

三、重复点识别与异常坐标修正

重复点有两种:一是 site_id 完全相同的记录重复,直接去重保留最新记录即可;二是编号不同但空间位置几乎重合的点,需要按距离阈值判断。环境监测点通常有最小间距要求,可设阈值如 50 米:两两计算球面距离,小于阈值的视为疑似重复,再结合点位名称、类型、监测指标人工确认。若确属同一物理点位的重复录入,保留属性更完整的一条,并把另一条的编号记入备注字段。

异常坐标的识别要结合业务范围。以某市为例,若研究区经度范围约为 116.0~116.8、纬度约为 39.6~40.2,则落在范围外的点即为可疑点。常见成因包括:经纬度写反、小数点错位、误用了投影坐标数值(如把米制坐标填进经纬度字段)、录入时多打一位数字。修正时优先回查原始台账或监测报告;无法回查的,可依据点位名称中的地址信息重新定位,并在 coord_flag 字段标注“已修正”或“待核实”,绝不能默默改数。

四、缺失属性补全与格式标准化

属性补全要区分“可推导”和“不可推导”。district 缺失时,可用点位坐标与行政区划面做空间叠加,取所在面要素的区县名称回填,这是可靠的空间派生;site_type 缺失时,可根据 site_name 中的“空气”“水质”“断面”等关键词规则推断,并标注推断来源;而 year(建站年份)属于事实性属性,无法从坐标推导,应保留为空并列入待补清单,不能随意填默认值。

格式标准化包括:点位名称统一去除多余空格与括号后缀,建立“标准名—别名”对照;site_id 统一为“类型前缀+行政区代码+序号”的规则,如 AQ-1101-001、WQ-1101-003;经纬度统一保留 6 位小数;监测指标统一为规范代码(如 PM2.5、PM10、O3、COD、NH3-N);空值统一用空字符串而非“无”“N/A”“-9999”等混用写法。

环境监测点数据清洗:输入—判断—处理—输出 原始点位清单 site_id / 名称 / 类型 lon / lat / crs 指标 / 行政区 / 年份 ① 坐标系统一 目标:CGCS2000 地理坐标 WGS84 → 沿用并标注 GCJ02 → 迭代纠正 ② 重复点识别 编号重复 → 去重 距离 < 50 m → 疑似 结合名称/指标确认 ③ 异常坐标修正 越界 / 写反 / 错位 回查台账优先 标注 coord_flag ④ 缺失属性补全 district:空间叠加回填 site_type:关键词推断 year:不可推导,留空待补 记录补全来源字段 ⑤ 格式标准化 名称去后缀、建别名表 编号规则统一 经纬度保留 6 位小数 指标代码、空值统一 清洗后点位数据 坐标统一、无重复 属性完整、格式规范 保留原始字段可回溯 附清洗日志与待补清单 判断:坐标是否越界? 在范围内 → 保留 越界 → 回查原始台账 无法回查 → 按地址重定位 标注“已修正/待核实” 关键判断依据 · 坐标系:以分析底图为准,GCJ02 必须纠正,转换前后位移应在数百米量级;位移过大说明原始标注有误。 · 重复点:编号相同直接去重;编号不同但距离小于阈值(如 50 m)需结合名称、类型、指标人工确认。 · 属性补全:可空间派生或规则推断的才补,事实性字段缺失应留空并列入待补清单,禁止填默认值冒充完整。

五、结果验证与交付物

清洗完成后不能只看表格“顺眼”,要做三项验证。第一,把清洗后的点位重新上图,与行政区划、河流或路网底图叠加,检查点位是否落在合理位置,尤其关注修正过的点和补全了行政区的点。第二,统计清洗前后记录数、重复删除数、坐标修正数、属性补全数,形成清洗日志,做到每一步可追溯。第三,抽查若干点位,用点位名称在原始台账中反查,确认坐标与属性对应关系没有错位。

建议交付一份可直接使用的点位清洗记录表,字段如下(示例值仅作格式演示):

site_id 标准名称 类型 lon_std lat_std crs_std coord_flag district 补全来源
AQ-1101-001 城北空气监测站 空气 116.412300 39.931200 CGCS2000 原始 城北区 原始记录
AQ-1101-002 工业园空气监测站 空气 116.503800 39.887600 CGCS2000 GCJ02已纠正 工业园 空间叠加
WQ-1101-003 东河断面采样点 水质 116.455100 39.902400 CGCS2000 坐标已修正 东河区 回查台账
WQ-1101-004 南湖采样点 水质 116.621700 39.845900 CGCS2000 原始 南湖区 原始记录
清洗过程中始终保留原始坐标、原始名称和原始属性字段,新增标准字段与标志字段。这样即使后续发现某一步处理有误,也能从原始数据重新派生,而不是在已改动的数据上反复修补。
最常见的错误是“只改标签不改数值”:把 GCJ02 点位的 crs 字段直接写成 CGCS2000,坐标数值却未纠正,导致点位整体偏移数百米。这类错误在单点检查时很难发现,但会系统性影响后续空间插值和缓冲区分析,必须通过转换前后位移量统计来拦截。

完成上述步骤后,这批点位数据才具备进入属性联接、空间分析与制图的条件。清洗的价值不在于把数据“改漂亮”,而在于让每一个坐标、每一个属性都有来源、有判断、有记录,使后续分析结论建立在可信的数据基础之上。