论文详解 | HDAM:破解 MAUP 的城市出行需求分析新方法,实现关键驱动精准识别
原文:Unveiling the key drivers of travel demand via hotspot analysis: a new approach to mitigate the modifiable areal unit problem
研究核心背景
随着全球化与城市化的快速推进,城市人口激增、交通出行方式多元化,加之环境可持续发展的需求,精准分析城市出行需求成为城市规划、交通管理和环境政策制定的核心基础,其不仅关乎居民个体出行的便利性,更直接影响交通资源优化配置、城市运行效率提升、环境污染治理和居民生活质量改善。但城市交通系统具有动态性与复杂性,出行行为和需求受社会经济、城市空间结构、建成环境等多因素交互影响,精准识别出行需求的关键驱动因素成为制定有效交通政策的关键。
而当前出行需求分析的核心痛点,在于空间分析中固有的可修改面单元问题(MAUP),这一问题直接导致出行需求研究结果的准确性、可靠性和可推广性大打折扣。MAUP主要体现为尺度效应和分区效应:尺度效应下,分析单元过细则易出现数据稀疏问题,无法捕捉出行需求的空间关联特征;单元过粗则会过度聚合数据,掩盖区域内的空间异质性,丢失关键细节。分区效应下,即便在同一尺度下,网格原点偏移、行政边界不同等差异化的边界划分方式,也会得出差异显著的出行需求分析结果。
此外,现有出行需求相关研究仍存在诸多不足:多数研究以行政边界、固定尺度网格为分析单元,对替代分析单元如何影响结果、如何从根源缓解MAUP缺乏深入探讨;部分基于路网、地理探测器确定最优网格尺度的方法,仍受限于网格框架的地理语义缺失、尺度固定问题;且现有研究多采用全域综合建模方式,对MAUP影响下出行热点的形成机制、真正驱动因素关注不足,同时缺乏统一的尺度选择标准,模型的普适性和可迁移性较差。在此背景下,亟需一种数据驱动的新方法,从源头重构分析单元,弱化MAUP的影响,实现出行需求关键驱动因素的精准识别。
核心创新方法:HDAM

研究提出的基于热点检测的出行需求关键驱动分析方法(HDAM),以数据驱动为核心,摒弃传统全域分区的思路,从源头重构分析单元,结合热点检测、空间建模与可解释人工智能,构建了完整的出行需求分析框架,核心分为三步:
同时,研究在HDAM基础上提出分层建模方法,采用自然断点法将出行热点按强度分为低、中、高三级,分别探究不同强度层级下出行需求的关键驱动因素,进一步提升模型分析的精准度和针对性。
关键实证研究结果

研究以哈尔滨绕城高速内的主城区为核心研究区,采用2024年4-5月的160余万条出租车订单数据和11.9万余条POI数据开展实证分析,同时以西安主城区为验证区完成跨城市普适性检验,核心结果如下:
R
2
R^2
R2达0.79、RMSE为1257.9,远优于其他分区方法,有效捕捉了出行需求的空间异质性,弱化了MAUP的影响。
R
2
R^2
R2达0.81,延续了在哈尔滨的优异表现,验证了HDAM在不同城市形态、社会经济特征和数据体系下的可迁移性和通用性。
研究的核心贡献与应用价值
import numpy as np
import pandas as pd
import geopandas as gpd
from scipy.stats import gaussian_kde
from shapely.geometry import Point, Polygon
import matplotlib.pyplot as plt
# ————————–
# 1. 数据预处理:加载出行数据(以出租车订单为例)
# ————————–
def load_taxi_data(file_path):
"""
加载出租车订单数据,提取经纬度坐标
:param file_path: 数据文件路径(csv格式,包含lon, lat字段)
:return: 经纬度数组、GeoDataFrame
"""
df = pd.read_csv(file_path)
# 过滤异常值(经纬度范围示例:哈尔滨主城区)
df = df[(df['lon'] > 126.3) & (df['lon'] < 126.7) &
(df['lat'] > 45.7) & (df['lat'] < 46.0)]
coords = np.vstack([df['lon'], df['lat']])
gdf = gpd.GeoDataFrame(df, geometry=[Point(xy) for xy in zip(df['lon'], df['lat'])], crs='EPSG:4326')
return coords, gdf
# ————————–
# 2. 自适应核密度估计(核心创新点)
# ————————–
def adaptive_kde(coords, bandwidth_adjust=0.1):
"""
自适应核密度估计:根据局部数据密度调整带宽
:param coords: 经纬度坐标数组 (2, N)
:param bandwidth_adjust: 局部带宽调整系数
:return: kde模型、密度值数组
"""
# 基础KDE(全局带宽)
kde = gaussian_kde(coords)
global_bandwidth = kde.covariance_factor()
# 计算局部密度,用于调整带宽
densities = kde(coords)
# 归一化密度值(0-1)
norm_densities = (densities – densities.min()) / (densities.max() – densities.min())
# 自适应带宽:高密度区减小带宽,低密度区增大带宽
adaptive_bandwidths = global_bandwidth * (1 – bandwidth_adjust * norm_densities)
kde.set_bandwidth(adaptive_bandwidths.mean()) # 应用自适应带宽
# 生成网格并计算密度(用于可视化和热点提取)
lon_min, lon_max = coords[0].min(), coords[0].max()
lat_min, lat_max = coords[1].min(), coords[1].max()
lon_grid, lat_grid = np.meshgrid(np.linspace(lon_min, lon_max, 200),
np.linspace(lat_min, lat_max, 200))
grid_coords = np.vstack([lon_grid.ravel(), lat_grid.ravel()])
grid_densities = kde(grid_coords).reshape(lon_grid.shape)
return kde, grid_densities, lon_grid, lat_grid
# ————————–
# 3. 基于BFS的热点提取(核心创新点)
# ————————–
def extract_hotspots(grid_densities, lon_grid, lat_grid, threshold_percentile=95):
"""
基于广度优先搜索(BFS)提取出行热点
:param grid_densities: 网格密度值
:param lon_grid/lat_grid: 经纬度网格
:param threshold_percentile: 热点密度阈值(百分位数)
:return: 热点区域列表(每个热点为Polygon)
"""
# 确定密度阈值(取Top N%为热点)
density_threshold = np.percentile(grid_densities, threshold_percentile)
# 标记热点网格
hotspot_mask = grid_densities >= density_threshold
# BFS提取连通的热点区域
visited = np.zeros_like(hotspot_mask, dtype=bool)
hotspots = []
rows, cols = hotspot_mask.shape
directions = [(–1,0), (1,0), (0,–1), (0,1), (–1,–1), (–1,1), (1,–1), (1,1)] # 8邻域
for i in range(rows):
for j in range(cols):
if hotspot_mask[i,j] and not visited[i,j]:
# BFS初始化
queue = [(i,j)]
visited[i,j] = True
hotspot_cells = [(i,j)]
while queue:
x, y = queue.pop(0)
for dx, dy in directions:
nx, ny = x+dx, y+dy
if 0<=nx<rows and 0<=ny<cols and hotspot_mask[nx,ny] and not visited[nx,ny]:
visited[nx,ny] = True
queue.append((nx, ny))
hotspot_cells.append((nx, ny))
# 将热点网格转换为地理多边形
cell_coords = [(lon_grid[cell], lat_grid[cell]) for cell in hotspot_cells]
if len(cell_coords) > 3: # 过滤过小的热点
hotspot_polygon = Polygon(cell_coords)
hotspots.append(hotspot_polygon)
return hotspots, density_threshold
# ————————–
# 4. 主函数:完整流程运行
# ————————–
if __name__ == "__main__":
# 1. 加载数据(替换为你的数据路径)
# 数据格式示例:csv包含lon(经度), lat(纬度)列
coords, gdf = load_taxi_data("taxi_orders.csv")
# 2. 自适应核密度估计
kde, grid_densities, lon_grid, lat_grid = adaptive_kde(coords)
# 3. 提取热点
hotspots, threshold = extract_hotspots(grid_densities, lon_grid, lat_grid)
# 4. 可视化结果
plt.figure(figsize=(12, 8))
# 绘制密度热力图
plt.contourf(lon_grid, lat_grid, grid_densities, cmap='Reds', alpha=0.7)
plt.colorbar(label='出行密度')
# 绘制热点区域
for hotspot in hotspots:
x, y = hotspot.exterior.xy
plt.plot(x, y, 'k-', linewidth=2)
# 绘制原始订单点(抽样显示,避免密集)
sample_points = gdf.sample(1000)
plt.scatter(sample_points['lon'], sample_points['lat'], c='black', s=1, alpha=0.3)
plt.title("HDAM方法:城市出行热点检测结果", fontsize=14)
plt.xlabel("经度")
plt.ylabel("纬度")
plt.tight_layout()
plt.show()
# 输出结果统计
print(f"检测到出行热点数量:{len(hotspots)}")
print(f"热点密度阈值({95}百分位):{threshold:.6f}")




