拿到这份东西,很多人的第一反应是“不就一张房价表嘛”,但真在项目里碰过地级市面板数据的人都知道,这里面的坑比想象中多得多。尤其是它同时包含了Excel和Shp两种格式,意味着这不只是一张统计表,而是一套可以对接GIS分析的空间数据集。2019到2025,跨度六年,逐月粒度,覆盖全国地级市,这几个条件叠在一起,数据的清洗、对齐、口径校验和空间化处理,每一项都是实打实的工作量。
这篇文章我不打算讲空泛的概念,就围绕这份数据的结构逻辑、处理流程、实操中会踩的坑,以及如何把Excel和Shp两种格式真正用好,拆开揉碎了说清楚。适合正在做城市研究、区域经济分析、房地产相关课题的同学,也适合刚接触空间数据分析、想把表格数据落到地图上的新手。
1. 这份数据到底是什么,为什么值得认真对待
1.1 标题拆解:六个关键词背后的信息量
先把标题逐词拆开看。“会员专享数据”说明这套数据不是公开渠道随手能抓的,大概率是某类数据平台或社群的付费整理产品,带有一定的稀缺性。“2019-2025”是时间跨度,六年整,覆盖了房地产周期里一个相当完整的波段。“地级市”是空间粒度,注意不是省级、不是县级,是地级市这一层,这是城市研究里最常用也最尴尬的层级——说细不细,说粗不粗,但恰好能撑起绝大多数横向对比。“逐月”是时间粒度,意味着一年12个截面,六年就是72期数据,数据结构上属于典型的面板数据。“新房房价”是核心指标,注意是“新房”,不是二手房,两者在统计口径、数据来源、波动特征上差别极大。“Excel/Shp格式”更关键,说明这套数据不只是表格,还配套了矢量边界,可以直接进GIS软件做空间可视化。
这六层信息叠起来,决定了一个基本判断:这不是一份可以拿Excel随便拉个折线图就交差的轻量数据,它具备做严肃研究的底子,但前提是你得把它处理对。
1.2 这类数据通常长什么样
以我接触过的同类数据集来看,Excel部分大概率是长表格和宽表格混着给的。长表格就是典型的“城市-时间-指标”三列结构,比如城市名、年月、新房均价,每一行是一个观测值;宽表格则是以城市为行、以年月为列,每行就是一座城市在72个月里的完整时间序列。Shp部分则是地级市行政边界,属性表里一般带有城市名称或行政区划代码,用来和Excel里的城市名做关联。
这里要提前说清楚:长表格适合做检索、筛选、建模,因为数据是“整齐”的;宽表格适合人眼直接看趋势,也适合转成一些面板模型需要的格式。但不管给的是哪种,真正干活的时候大概率都需要自己再加工一遍。不要指望拿到手就能直接用,这个心态要放平。
1.3 适合谁用,能解决什么问题
如果你是做城市经济研究的,这份数据可以支撑房价与人口流动、产业结构、基础设施投入之间的关联分析;如果你是做房地产投资分析的,六年的月度数据足够看清一座城市的房价节奏和波动幅度;如果你是做GIS可视化或规划类项目的,Shp文件加房价属性表,能直接产出一套“城市房价动态地图”。当然,如果你只是好奇自己所在城市的房价走势,也完全可以把对应城市的72个月数据拉出来,画个趋势图,比任何新闻里的碎片信息都直观。
2. 数据处理第一步:把Excel里的“脏数据”收拾干净
2.1 拿到文件后先别急着分析,做三件事
第一步,检查数据结构。打开Excel后先看前几十行,确认是长表格还是宽表格,确认每一列是什么含义。我见过很多数据集,表面是整齐的表格,但实际藏着合并单元格、表头分层、单位混用这类问题。尤其是“元/平方米”和“万元/套”这种单位混杂的情况,不清理干净,后面计算全部跑偏。
第二步,检查城市名单。把城市列去重,数一数一共有多少个城市,再和国家行政区划代码表对照。这里最容易发现的问题是城市名有别名(比如“呼和浩特”写成“呼市”),或者在某个年份改了名、调整了行政区划(比如某某市2019年撤县设区,导致口径变化)。城市名是后面关联Shp地图的关键字段,这一关不过,地图匹配一定出乱子。
第三步,检查时间字段。确认年月列的格式是“2024-01”这样的标准字符串,还是“202401”这种纯数字,还是Excel日期格式。三种格式在不同环节各有用处,但如果不统一,后面做时序分析或者转面板数据的时候会被反复坑。
2.2 缺失值和异常值的处理策略
六年、地级市、逐月,这三个条件叠加,数据几乎不可能完整。常见的情况有三种:一是某城市在某些月份没有成交记录,导致空缺;二是某些城市房价忽高忽低,出现明显脱离相邻月份趋势的异常值;三是少数城市可能在某个时间段调整了统计口径,导致前后数据不可比。
我推荐的策略是:先做“可视化检查”。把每个城市的时间序列拉成折线图,一眼就能看出哪些点异常突兀。对于缺失值,如果前后月份都有数据,可以用线性插值补齐;如果连续缺失超过三个月,建议标记为缺失,不要强行填充。对于异常值,先确认是不是统计口径变化,如果只是单点异常,可以考虑用前后三个月的均值做平滑替换。但所有处理过的位置,一定要另起一列做标记,保留原始数据不动。
重要:任何数据清洗操作都不应该在原始文件上直接做。复制一份原始文件备份,在副本上操作。这个习惯能救命的场景太多了,尤其是当你清洗到一半发现处理逻辑有误的时候。
2.3 口径问题:为什么房价数据不能简单横向比
这是这份数据里最微妙的地方。新房房价在不同城市、不同统计来源下,口径差异很大。有的城市发布的是“成交均价”,有的发布的是“备案均价”,有的则是“网签均价”。这些口径对同一座城市的同一月,数值可能差出百分之五到百分之十。另外,城市的成交结构也会影响均价——某个月高端楼盘集中入市,均价就会跳升,但这不代表整个城市房价普涨。
所以在做任何横向比较时,我建议先算“城市对自身的同比增速”,再做城市之间的对比,而不是直接拿绝对价格比较高低。绝对价格受城市能级、房屋品质、统计口径影响太大,增速的相对变化更能说明问题。
3. 从Excel到Shp:空间数据结构与属性关联原理
3.1 为什么有了Excel还不够,一定要Shp
很多初学者会问:我都有全国地级市的房价数据了,为什么还需要Shp文件?答案是:Excel只有“属性”,没有“位置”。一张写着“某某市新房均价12000元/平方米”的表,你不知道这座城市在地图上的哪个位置,边界长什么样,跟哪些城市接壤。Shp文件是GIS领域的标准矢量格式,存储的是每个城市的边界、轮廓和坐标信息。把房价数据挂到Shp上,Excel就从一个“电话簿”变成了一张“地图”。
从技术原理上说,Shp文件本质上是若干个文件组成的集合,至少包括主文件(.shp,存几何信息)、索引文件(.shx,存几何索引)、属性表文件(.dbf,存属性信息)。有时候还会附带投影文件(.prj)、编码文件(.cpg)。这些文件必须放在同一个文件夹、保持同名,缺失任何一个,GIS软件都可能报错。
3.2 字段匹配的核心逻辑
要把Excel里的房价数据关联到Shp地图上,核心就是“字段匹配”。Shp的属性表里通常有两个关键字段:一是城市名称(可能叫NAME、CITYNAME等),二是行政区划代码(可能叫ADCODE、CODE等)。Excel里对应的则是城市名或代码。两个表做关联,就是按这两个字段把它们连成一张表。
最容易踩的坑是编码不一致。比如Shp里的城市名是“北京市”,Excel里是“北京”,或者Shp里是“巴音郭楞蒙古自治州”,Excel里是“巴州”。字符不同,关联就直接失效,而且很难排查,因为数据量大了之后根本看不出哪行没匹配上。建议的做法是:先做一次全量匹配,把没有匹配上的城市单独导出来核对,手工修正Excel侧的城市名,再重新关联。
3.3 地理坐标系和投影坐标系
如果你要把房价数据做空间分析,比如计算“某城市周边300公里内的平均房价”,就绕不开坐标系的问题。Shp文件里的坐标信息是“地理坐标”,单位是度,直接用它量距离是没有意义的。需要先定义投影坐标系,把度转换成米。
实际操作中,国内的公开数据最常用的投影是“Albers等面积投影”或“Lambert等角投影”,全国范围做分析时用这两种比较稳妥。如果你只是用某个省级或市级范围做局部展示,用“UTM投影”也可以。不要用Web Mercator做面积测算,它的变形会随着纬度升高而加剧,算出来的面积和距离偏差很大。
4. 核心实操:一套可以直接复用的完整处理流程
4.1 工具选型:Excel、Python、QGIS的搭配方案
处理这套数据,主流方案有三类。第一类是纯Excel操作,适合数据量小、只做简单筛选和制图的场景,但遇到72个月乘200多个城市,性能就开始吃力了。第二类是Excel加Python,用pandas做数据清洗、长宽转换、缺失值处理,再把结果导出成新的Excel或CSV,这套组合最灵活,也是我最推荐的。第三类是Excel加QGIS,重点在空间可视化,把房价数据挂到Shp后直接做分级设色地图、时间滑块动画。
工具没有绝对的高下之分,关键是匹配你的目标:只做单城市趋势分析,Excel就够了;做多城市面板模型,必须上Python;做地图可视化,必须用GIS软件。三者不是互斥关系,而是可以串联的流水线——我自己的习惯是:Excel看数据、Python洗数据、QGIS出图。
4.2 用Python做数据清洗的参考流程
假设你已经有了一个长表格,列名是city、month、price。下面是一段可以直接套用的清洗代码思路,不用完全照抄,重点是流程:
import pandas as pd # 读取数据 df = pd.read_excel("raw_data.xlsx") # 统一城市名:去掉首尾空格、统一括号和地名后缀 df["city"] = df["city"].str.strip() df["city"] = df["city"].str.replace(" ", "") # 全角空格 # 统一时间格式:如果是"2024年1月",转成"2024-01" df["month"] = pd.to_datetime(df["month"], format="%Y年%m月").dt.strftime("%Y-%m") # 删除完全重复的行 df = df.drop_duplicates() # 排序、索引重置 df = df.sort_values(["city", "month"]).reset_index(drop=True) # 生成宽表格 wide = df.pivot_table(index="city", columns="month", values="price") # 保存 wide.to_excel("wide_price.xlsx")这一段代码完成的其实是四件事:字符串清洗、时间格式化、去重、宽窄转换。看起来简单,但每一步都有讲究。比如str.strip()处理的是城市名里不可见的空格,“某某市”和“某某 市”肉眼难辨,机器判为两个不同城市,关联的时候就会漏掉。
4.3 把房价挂到Shp上:QGIS手动关联步骤
如果你不想写代码,QGIS完全可以胜任字段关联这件事。具体步骤是:
第一步,打开QGIS,通过“图层”菜单添加Shp文件。如果Shp的编码不对,属性表里会出现乱码,需要在“数据源管理器”里手动指定编码,通常用UTF-8。
第二步,在图层上右键,打开属性表,确认城市名字段的准确名称。比如字段叫“NAME”,记住它。
第三步,在“图层”菜单里选择“添加矢量图层”,把整理好的Excel表格添加进来。
第四步,在“处理”工具箱里搜索“按字段值连接属性”,输入Shp图层和Excel图层,指定Shp的对应字段和Excel的对应字段,连接类型选择“一对一”,运行之后Shp的属性表里就会多出房价数据的字段。
第五步,右键图层,打开“属性”,选择“符号化”,按“分级”做颜色映射,字段选最新月份的房价,模式选“自然间断点”或者“分位数”,在“图例”里勾选“显示图例”,一张基础的城市房价地图就出来了。
4.4 动态地图:让72个月“动”起来
静态地图只能展示一个时间截面,但这套数据有72个月,浪费可惜。QGIS里有一个叫“时间管理器”的插件,可以把属性表里带月份字段的图层按时间播放。做法是:在图层属性里设置“时间”相关属性,把“月份”字段指定为时间字段,然后打开时间管理器,设置好起始和结束时间,就可以拖拽时间轴,看房价从2019年到2025年的空间分布变化。
这个功能做出来的效果相当直观:你能清晰地看到高房价区域如何从沿海大城市逐步扩散到内陆强省会,再到部分三四线城市,也能看到某些城市群的房价如何潮起潮落。这种动态地图用于项目汇报或者课题展示,效果远胜过一百个静态表格。
5. 实战中常见的坑与排查技巧
5.1 城市名匹配不上:八成的项目卡在这一步
我经手过的数据项目里,最普遍的问题就是城市名匹配失败。原因大同小异:缩写、别名、全角半角不统一、行政代码差异。解决办法是通过“模糊匹配”先找出相似项,再手工批量确认。
在Python里可以用difflib库的SequenceMatcher做相似度比对,也可以直接用fuzzywuzzy库的token_set_ratio,把相似度在80分以上的城市成对列出来,你只需要快速浏览确认,省去大量手工查找时间。这个技巧在处理“多个来源合并”的场景里特别适用。
5.2 房价数据单位混用:千万留意“元/平”和“万元/平”
“均价12000”和“均价1.2”,看起来差了一个数量级,但前者是“元每平方米”,后者是“万元每平方米”,单位不同。这类单位混用问题在手工整理的数据里非常常见。建议的做法是在清洗阶段用一个归一化处理,把所有价格统一为“元/平方米”。如果无法确定某一列的单位,宁可引用外部权威数据做抽样核对,也不要猜测。
抽样核对的具体方法是:随机挑出10个城市、每个城市挑出3个月份,把数据集里的数值和公开的权威渠道交叉验证一下,确认单位无误后再做后续分析。这个步骤成本很低,但能避免整条分析链路的毁灭性偏差。
5.3 Shp文件加载不了:先查文件完整性
QGIS里加载Shp文件报错,最可能的原因是缺少配套文件或者文件路径中有中文字符或特殊符号。解决方法是:把整个Shp文件所在的文件夹复制到纯英文路径下(比如D:/data/shp/),确认文件夹内同时存在.shp、.shx、.dbf三个基础文件,再重新加载。另外,文件名里不要有空格,也不要有括号,很多稳定性的问题都是这样的小细节引起的。
5.4 时间序列里的断档:用“城市×月份”完整矩阵排查
如果某些城市在个别月份没有数据,直接做成宽表格就会发现对应位置是空的。这时候建议先生成一份“城市×月份”的完整行列组合,再左连接原始数据。这样能迅速定位哪些城市在哪些月份缺数据,不会因为某一行的缺失就漏掉一整段分析。
all_cities = df["city"].unique() all_months = pd.period_range("2019-01", "2025-12", freq="M").strftime("%Y-%m") full_index = pd.MultiIndex.from_product([all_cities, all_months], names=["city", "month"]) df_full = df.set_index(["city", "month"]).reindex(full_index).reset_index()这段代码生成的df_full就是一张完整的城市×月份骨架表,缺失值一定是NaN,一眼就能看出来。
5.5 坐标偏移:边界“飞”了怎么办
有时候加载Shp后,地图边界和底图对不上,明显偏移。这时候基本可以判断是坐标系不匹配。右键图层,查看“属性→信息→坐标系”,如果显示的是WGS 84,而你的底图是GCJ02或BD09,那就需要做坐标转换。国内公开的地图数据里,这三种坐标系之间的转换很常见,但需要注意:GCJ02和BD09之间的转换算法不是单纯线性变换,网上有现成的转换库,直接用就行,不要自己写公式。
6. 进阶:这份数据还能怎么玩
6.1 计算“房价增速”和“波动率”两个衍生指标
原始数据只有价格,但很多分析需要的是增速和波动率。增速可以用“同比”算:2024年1月的价格除以2023年1月的价格,再减1,代表此刻比一年前涨了多少。波动率可以用“近12个月价格的标准差除以均值”来算,衡量一座城市房价的稳定性。把这两个指标算出来挂到地图上,能看到完全不同的空间格局——有些城市绝对价格不高,但波动极大;有些城市价格高企,但走势极其平稳。
6.2 城市群视角的切片分析
地级市是散点,但城市群是网络。把城市按所属城市群分组(比如长三角、珠三角、成渝、长江中游等),比较各城市群内部的房价均值、中位数和极差,可以快速回答“哪个城市群内部房价分化最严重”这类问题。极端情况下,你甚至可以用最贵城市和最便宜城市的比值来构建一个“城市群内部分化指数”。
6.3 与人口、产业数据的多维叠加
房价数据单独看是一个维度,但如果叠加人口净流入、产业园区数量、基础设施投资等数据,就能做更有深度的关联分析。操作上,你需要把人口和产业数据同样处理成“城市×年份”的格式,然后和房价数据按城市名、年份合并成一张宽表,再跑相关性分析或者简单回归。注意:相关不代表因果,这个常识要记住,但做探索性分析是完全够用的。
7. 写在最后的实操心得
这套数据的核心价值不在于那张Excel表本身,也不在于Shp文件的矢量边界,而在于它们组合后创造出的分析空间。我在实际处理这类数据时最深的体会是:数据清洗永远比预期的时间长得多,尤其是城市名统一和时间格式处理这两步,几乎每次都要返工。建议你在开始动手之前就把清洗规则想清楚,写成一个可以反复执行的流程,而不是手动逐项修。
另外一个值得养成的习惯是:每一个处理步骤都保留一份中间结果。清洗前的原始数据、清洗后的长表格、宽表格、挂了Shp的空间数据,分文件夹存好,命名带日期。这样哪怕分析做到一半发现思路要调整,也可以快速回退到任意一个中间节点,而不是从头再来。
最后说一点:这六年刚好覆盖了一个完整的楼市周期,如果你能把这72个月的数据用活,做出来的分析和洞察会远超很多只靠报道和感觉得出的判断。数据是死的,但把它用好之后产生的东西,是可以真正拿去支撑决策的。