
本系列第三篇(完结)。Part 1[1] 讲全局 Moran’s I,Part 2[2] 讲 LISA 局部聚类。本篇做区域对比、时间序列分析和最终结论。
国家统计局 70 城没有自带区域标签,需要手动分组:
REGIONS = {
"京津冀": ["北京", "天津", "石家庄", "唐山", "秦皇岛"],
"长三角": ["上海", "南京", "无锡", "杭州", "宁波", "合肥", "温州", "金华", "徐州", "扬州", "蚌埠", "安庆"],
"珠三角": ["广州", "深圳", "惠州", "韶关", "湛江"],
"海西+海南": ["福州", "厦门", "泉州", "海口", "三亚"],
"中部": ["武汉", "长沙", "郑州", "南昌", "太原", "洛阳", "平顶山", "宜昌", "襄阳", "岳阳", "常德", "九江", "赣州", "济宁", "烟台", "济南", "青岛"],
"西部": ["重庆", "成都", "西安", "贵阳", "昆明", "兰州", "西宁", "银川", "乌鲁木齐", "南宁", "桂林", "北海", "泸州", "南充", "遵义", "大理", "呼和浩特", "包头"],
"东北": ["沈阳", "大连", "长春", "哈尔滨", "丹东", "锦州", "吉林", "牡丹江"],
}
def assign_region(city):
for region, cities in REGIONS.items():
if city in cities:
return region
return "其他"
gdf['region'] = gdf['CITY'].map(assign_region)
分组有争议吗? 有。蚌埠、安庆同时被长三角和中部"认领"(代码按顺序匹配,先命中长三角)。山东的济南、青岛被归入"中部"而非"东部"。这些是简化处理,实际分析中应该用国家统计局的标准区划,或根据研究目的自定义。
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(18, 7))
# 左图:区域平均累计涨幅
reg_cum = gdf.groupby('region')['cum_return'].agg(['mean', 'std']).sort_values('mean', ascending=True)
colors_cum = ['#4e79a7' if r != '海西+海南' else '#e15759' for r in reg_cum.index]
axes[0].barh(reg_cum.index, reg_cum['mean'], xerr=reg_cum['std'],
color=colors_cum, alpha=0.85, edgecolor='white', capsize=4)
for i, (name, row) in enumerate(reg_cum.iterrows()):
axes[0].text(row['mean'] + 1, i, f\"{row['mean']:.1f}%\", va='center', fontsize=9, fontweight='bold')
axes[0].set_xlabel('平均累计涨幅(%)')
axes[0].set_title('区域平均累计涨幅', fontweight='bold')
axes[0].grid(True, axis='x', alpha=0.2)
# 右图:区域平均波动率
reg_vol = gdf.groupby('region')['volatility'].agg(['mean', 'std']).sort_values('mean', ascending=True)
reg_vol['mean_pct'] = reg_vol['mean'] * 100
reg_vol['std_pct'] = reg_vol['std'] * 100
axes[1].barh(reg_vol.index, reg_vol['mean_pct'], xerr=reg_vol['std_pct'],
color=colors_cum, alpha=0.85, edgecolor='white', capsize=4)
for i, (name, row) in enumerate(reg_vol.iterrows()):
axes[1].text(row['mean_pct'] + 0.5, i, f\"{row['mean_pct']:.1f}%\", va='center', fontsize=9, fontweight='bold')
axes[1].set_xlabel('平均波动率(%)')
axes[1].set_title('区域平均波动率', fontweight='bold')
axes[1].grid(True, axis='x', alpha=0.2)
plt.suptitle('区域对比:涨幅 vs 波动率', fontsize=15, fontweight='bold', y=1.02)
plt.tight_layout()
plt.savefig('regional_comparison.png', dpi=150, bbox_inches='tight')
区域对比:涨幅 vs 波动率
两个排名几乎完全一致:
排名 | 区域 | 平均涨幅 | 平均波动率 |
|---|---|---|---|
1 | 海西+海南 | 128.6% | 128.6% |
2 | 珠三角 | 96.8% | 96.9% |
3 | 长三角 | 93.9% | 84.1% |
4 | 京津冀 | 105.9% | 77.0% |
5 | 西部 | 83.6% | 75.5% |
6 | 中部 | 78.8% | 71.8% |
7 | 东北 | 68.7% | 71.7% |
海西+海南在涨幅和波动率上都排第一,东北都排最后。但注意一个例外:京津冀涨幅排第 2(105.9%),波动率只排第 4(77.0%)——说明京津冀涨得多但涨得稳,政策管控压制了波动。
cities = ['北京', '上海', '深圳', '广州', '成都', '武汉', '温州', '三亚', '大连', '贵阳']
fig, ax = plt.subplots(figsize=(14, 8))
for city in cities:
c = df_mom[df_mom['CITY'] == city].sort_values('DATE')
cum_idx = (c['index_value'] / 100).cumprod() * 100
ax.plot(range(len(cum_idx)), cum_idx, label=city, linewidth=1.5, alpha=0.8)
ax.axhline(100, color='gray', linestyle='--', linewidth=0.8, alpha=0.5)
# 标注关键政策节点
events = {24: '2008 金融危机', 96: '2014 限购放松', 120: '2016 去库存', 180: '2021 调控收紧'}
for month, label in events.items():
ax.axvline(month, color='red', linestyle=':', linewidth=0.8, alpha=0.4)
ax.text(month + 1, ax.get_ylim()[1] * 0.95, label, fontsize=8, color='red', alpha=0.7)
ax.set_xlabel('月份(2006.01 起)')
ax.set_ylabel('累计指数(基期=100)')
ax.set_title('10 城房价指数累计走势(2006-2026)', fontweight='bold')
ax.legend(loc='upper left', fontsize=9)
ax.grid(True, alpha=0.2)
plt.savefig('time_series.png', dpi=150, bbox_inches='tight')
10 城房价累计走势
看图要点:
三篇教程下来,核心发现可以用一张表总结:
分析方法 | 变量 | 结果 | 含义 |
|---|---|---|---|
全局 Moran’s I | 累计涨幅 | I = -0.007, p = 0.44 | 涨跌幅没有空间聚集 |
全局 Moran’s I | 波动率 | I = 0.30, p = 0.001 | 波动率有显著空间聚集 |
LISA 局部聚类 | 波动率 | 8 城显著,HH=三亚/海口/北海/湛江 | 海南+北部湾是唯一波动率热点 |
区域对比 | 两者 | 排名几乎一致 | 高涨幅区域也是高波动区域 |
时间序列 | 累计走势 | 2014 年后急剧分化 | 城市分化在特定年份突然拉开 |
一句话结论:买房不用看邻居涨了多少(涨跌幅没有空间规律),但如果你的城市波动率高,周边城市大概率也高(波动率有空间规律,尤其是海南北部湾)。
参考链接
[1] https://www.renhai.online/blog/geospatial-data-analysis/python-spatial-autocorrelation-housing-70cities
[2] https://www.renhai.online/blog/geospatial-data-analysis/python-lisa-local-autocorrelation-housing