搞地理数据分析的朋友大概都踩过这个坑:手里拿着从高德、百度或者OpenStreetMap导出的POI数据,心想这下稳了,结果一跑脚本,报错提示主键冲突或者数据量大得离谱。仔细一对比,发现同一个商场、同一家连锁店被导出了好几份,坐标微差一点点,名字还带着空格后缀。这种Geo数据分析有好几个重复的怎么办?别急,这其实是新手进阶必过的鬼门关。
我之前接手过一个本地生活服务的清洗项目,甲方给了一堆竞品门店数据。乍一看有五千多家店,但我去地图上随手搜“星巴克”,发现有些坐标偏移了十几米,系统里却算作两家店;更离谱的是,因为抓取时间不同,有的数据里电话是旧的,有的是新号的,但门店主体完全一样。要是直接拿着这些脏数据去做热力图或者辐射范围分析,结果绝对会打脸。你看到的“繁荣”可能只是数据冗余堆出来的假象。
解决这事儿,不能光靠肉眼挑,得上点“狠活”。第一步,肯定是空间去重。很多初级分析师喜欢直接用Excel删重复行,这招在普通表格管用,但在GIS里是耍流氓。因为地理数据讲究的是“位置相近”,而不是“坐标完全相等”。比如两个点,一个经纬度是116.397, 39.908,另一个是116.3971, 39.9081,在地球上只隔了两米,但在数据库里它们是两个完全不同的ID。这时候得用PostGIS或者Geopandas里的距离过滤法。我们可以设定一个阈值,比如50米。先按名字或店铺类型分组,然后在每组内计算点与点的距离,把距离在50米以内的点,只保留ID最老或者数据质量最高的那一个。这就好比在拥挤的地铁里,把靠得太近、实为同一人的乘客,只算作一个个体。
光去空间重复还不够,还得去语义重复。这就是“geo数据分析有好几个重复的怎么办”的第二个难点。比如“肯德基(朝阳大悦城店)”和“肯德基-朝阳大悦城”,虽然名字不一样,但指代的是同一家。这时候就得结合字符串模糊匹配。我自己常用的是SimHash或者简单的Jaccard相似度算法,给名字打分。如果相似度超过85%,且空间距离在50米以内,那就大概率是重复项。不过这里有个坑,就是那些连锁店,像“全家便利店”、“罗森便利店”,它们名字相似但确实是不同的店。所以,一定要结合行政区划(POI ID)或者具体的门头图片来辅助判断,不能脑子一热全给扔了。
还有一个容易被忽略的隐形重复,就是同一实体在不同坐标系下的转换误差。如果你的数据源混杂了WGS84(国际坐标)和GCJ02(火星坐标),直接叠加在地图上,那些重复的点会呈现出一种诡异的“双影”效果,两个点中间隔着几十米。这种情况得先统一坐标系,用标准的转换算法把偏差校正过来,再去重,不然前面做的所有清洗都是白费功夫。
说点实在的,别指望有一个万能工具点一下就能完美解决。真实的数据清洗往往是脏活累活。我建议你建立一个小样本测试集,先拿几百条数据跑一遍你的去重逻辑,看看有没有误杀(把两家店当成一家了)或者漏网(同一个店没去重)。记得定期复核,因为商业世界的变化比代码迭代快,今天合并的店,明天可能因为并购又分开了。
最后给几点操作建议。如果是小规模数据,直接用QGIS的属性表功能,加一个字段计算距离,筛选后手动复核是最稳妥的。如果是大规模数据,必须学点Python,用Geopandas或者Shapely库写脚本,虽然前期配置环境有点麻烦,但后期批量处理效率高得吓人。还有,一定要保留原始数据的备份,去重后的数据虽然干净了,但那是经过人工意志干预的,原始数据才是真理。遇到搞不定的奇葩数据,比如那些名称极度不规范的小作坊,别硬抠逻辑,直接去地图实景看看,有时候看一眼门头照片,比算一万次相似度都管用。如果你卡在坐标系转换或者模糊匹配的代码实现上,欢迎来聊聊,别一个人死磕报错日志,那是程序员最容易掉发的地方。