
数据挖掘:一幅隐藏了 160 年的城市地图

DBSCAN聚类
你是否想过,上海其实有两个“世界”?
一个是看得见的,陆家嘴的摩天大楼,武康路的老洋房,南京路步行街的霓虹灯火。这是一个由钢筋水泥和玻璃幕墙构成的现代都会。
另一个,则隐藏在不起眼的路牌里。当你从静安区的“西康路”出发,一路向东,可能会依次经过“成都北路”、“重庆北路”、“黄陂南路”,最终抵达黄浦江边的“福建中路”和“江西中路”。不知不觉间,你已经用脚步完成了一次从中国西南到东南的微缩旅行。

上海的“西康路”得名于中国原西康省,不过在 1955 年,西康省被撤销,其辖区分别并入四川省和西藏自治区 黄陂南路代表湖北省武汉市黄陂区:“黄陂南路”最初名为“贝勒路”,1943 年以湖北黄陂县(今武汉市黄陂区)命名为“南黄陂路”,1946 年正式定名为“黄陂南路”并沿用至今。

上海路牌实拍——图片来源于网络
这个有趣的现象,很多人也有所察觉。
比如我刷到小红书上自制的一张图,来自 “62 咸鱼讲啥西”发布了一篇小红书笔记[1]:

为了验证这个趣闻,我决定用代码和地图来验证一下。
我们的故事,并非从整个现代上海的宏大地图开始,而是缩窄到核心城区。
我首先做了一个决定:将目光锁定在黄浦、徐汇、长宁、静安、普陀、虹口和杨浦七个区域。

1939年大上海市街地圖
虽然对照1939 年的地图[2],远不止这些区域这里。但是我们选择的区域也比较典型了。
摆在我面前的第一个难题,是数据的“破碎感”。原始数据里有超过 36 万条路段,同一条“南京东路”,在地图上却是由上百个互不相连的细小线段组成的“碎片”。

南京西路
如果直接分析这些碎片,就像试图通过一堆尘土来研究一件摔碎的古董,毫无意义。
在网络拓扑中,这是从 OpenStreetMap 等标准来源下载的路网数据,为了保证网络的拓扑关系(即,知道哪条路和哪条路是连通的),在每一个交叉口,路段(LineString)都必须被打断成独立的小段。如果我们为“南京西路”的每一小段都计算一个质心,那么在“南京西路”这条路上就会产生密密麻麻几十个点,这会给聚类分析带来巨大的噪声和权重偏差。也会产生可视化混乱。 要解决这个问题,我们需要在分析流程中增加一个关键的数据预处理步骤——道路合并。
因此,我必须进行一次数字世界的“文物修复” 。我让程序将所有同名的、在空间上首尾相接的碎片,重新“焊接”成一条完整的道路。这个过程是枯燥的,但结果是震撼的:在我的研究范围内,将近五万条道路碎片,被修复成了 1320 条我们认知中“完整”的道路。数据量骤减 97%,但信息的价值却提升了 100 倍。我们终于从一片数据的废墟中,重建了真实世界里那一条条连贯的街道。”

1320条道路
接着我构建了一个省市区——省份的地名词典:

有了完整的路和地名词典,我满怀信心地进行了第一次匹配,结果却给我泼了一盆冷水。我的程序天真地把“金沙江西路”识别为了“江西省”,把“上海东路”匹配给了青海的“海东市”。而且,上海市应该不应该在我的地名词典里面!我自己匹配自己?
于是我需要思考解决方案:
Aho-Corasick算法,它能像一个超级搜索引擎,一次性在所有路名中高效地查找字典里的所有地名。
匹配结果预览
当我的侦探完成工作,一张惊人的画卷在我面前展开。我将所有与省份相关的道路,用不同的颜色标注在地图上:

上海地名聚合道路之后按照质心分布图(合并省份所有道路)
上海的市中心,真的藏着一幅中国地图!
这并非巧合,它的源头,甚至要追溯到一个半世纪以前。
1862 年,英国领事麦华陀发布了一份《上海马路命名备忘录》。这份看似不起眼的文件,为上海的街道定下了一个影响至今的规则:南北向干道以中国省份命名,东西向则以该省的城市命名。这套规则,既方便了殖民者的行政管理,又在无形中透露出一种“掌控中国版图”的野心。于是,在最初的租界里,“四川路”与“南京路”交汇,第一块“微缩中国”的拼图被悄然放下。
最初,我将每个省在上海的所有道路视为一个整体,计算出一个“代表点”。这确实绘制出了一幅粗略的“中国地图”,但这种简化也隐藏了太多细节。一个点,无法告诉我们这些来自同一个省的道路,在上海是紧密抱团,还是分散四方。
并且我是用了 KMeans 聚类算法,无法智能感知内部聚类情况,也无法筛选掉离群点。
为了看到更真实的图景,我决定深入每个省份的内部,去探寻它们的 “社区结构” 。
于是我使用了 DBSCAN 聚类算法:

KMeans聚类和DBSCAN聚类的区别
我将每条路都“点化”,然后用一种名为DBSCAN的密度聚类算法,去自动发现那些由来自同一个家乡的道路组成的“小团体”。

DBSCAN聚类
算法精准地勾勒出了每个省份路名的聚集区域,我们由此得以窥见它们不同的“性格”:有的省份路名紧密抱团,形成单一的核心社区;有的则分散四方,形成多个遥相呼应的“飞地”。这幅地图,因此变得更加立体和丰满。
翻阅匹配之后的记录,我惊喜地发现:上海的“长宁路”,其命名源头并非脚下的长宁区,而是远在千里之外的四川省长宁县。

长宁县——四川省宜宾市下辖县,来源于百度百科
又比如:“长乐路”中的“长乐”并非表达“长久快乐”之意,而是直接借用了福建省福州市辖区之一:长乐区。

长乐路的匹配结果
历史的车轮滚滚向前。1943 年,汪伪政府为了清除英美殖民痕迹,进行了一次大规模的路名更改,将更多中国地名覆盖了原有的西式路名。而到了 1950 年代,新生的人民政府在更大规模的城市建设中,将这套命名法以前所未有的系统性和魄力,推向了极致。
至此,这幅隐藏在上海肌理中的“中国地图”,被一块块地完整拼合。它早已超越了殖民者的初衷,变成了一场宣告主权、重塑国人身份认同的伟大宣言。每一块路牌,都成了无声的爱国主义丰碑。
上海,用它的路牌告诉我们:无论你来自何方,无论你身处城市的哪个角落,总有一条路,能唤起你对故乡的记忆。
你的家乡是哪一个?欢迎晒出你家乡的路牌。
这次“数据考古”虽然为我们揭示了上海路网背后宏大的叙事,但也有一些缺陷:
1. 词典的边界:被遗忘的山川与历史
2. 道路的定义:被忽略的“毛细血管”
3. 名称的唯一性:重名的挑战
P.S. 如果你对我们这次“城市考古”的技术细节感兴趣,想知道我们是如何一步步驯服数据、让它开口说话的,欢迎访问我的 GitHub 仓库,那里有此处项目的源代码。 Urban-Spatial-Data-Analysis:上海路网聚合[3]
欢迎在评论区里疯狂吐槽你在 ArcGIS、python 代码里遇到的烦心事,或者聊聊你对这个系列、对哪个技术方向最感兴趣。你们的反馈会直接影响我后续内容的侧重点!
参考资料
[1]
一篇小红书笔记: http://xhslink.com/m/4wD7qWGFbHj
[2]
1939 年的地图: https://www.virtualshanghai.net/%E5%9C%B0%E5%9B%BE/%E6%94%B6%E9%9B%86?ID=35
[3]
Urban-Spatial-Data-Analysis:上海路网聚合: https://github.com/renhai-lab/Urban-Spatial-Data-Analysis-Notebook/tree/main/4-%E7%A9%BA%E9%97%B4%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/%E5%85%B6%E4%BB%96%E6%A1%88%E4%BE%8B/%E4%B8%8A%E6%B5%B7%E8%B7%AF%E7%BD%91%E8%81%9A%E5%90%88
[4]
个人网站: https://www.renhai.online/
[5]
我的知乎: https://www.zhihu.com/people/Ing_ideas
[6]
我的博客: https://www.renhai.online/blog
[7]
我的 GITHUB: https://github.com/renhai-lab
[8]
我的 GITEE: https://gitee.com/renhai-lab
[9]
RSS: https://www.renhai.online/rss.xml