如何按指定半径与最小点数阈值聚类经纬度地理数据
问题根因
DBSCAN、OPTICS的输出不符合预期是算法固有逻辑导致的:
两类算法均属于密度连通聚类,规则为「核心点eps半径内邻点数量≥min_samples时生成核心簇,密度可达的核心点会自动合并为同一个簇」,无法匹配你提出的「簇内所有点到簇心距离≤4km、簇心4km覆盖范围内的点归为同簇」的硬约束。实际运行中常出现两个相距6-8km的高密度点群,因中间零散点形成连通路径被合并为跨度超10km的大簇,簇边缘点到簇心距离远超4km限制。
正确实现方案
你的需求属于带最小样本数约束的固定半径密度峰值聚类,不要使用密度连通类算法,按以下流程实现:
步骤1:坐标投影转换
直接使用经纬度计算haversine距离效率低,先将WGS84经纬度转换为以米为单位的等距投影坐标,后续距离计算直接用欧氏距离即可,4km尺度下投影误差小于1%:
- 若数据覆盖国内区域,选择对应经度带的CGCS2000 3度带投影即可;若为全球范围数据,用对应UTM分带投影或Web墨卡托投影做近似计算。
import pandas as pd import numpy as np from pyproj import Transformer from sklearn.cluster import MeanShift # 读取原始数据 df = pd.read_excel('dataset.xlsx') # 初始化坐标转换器:WGS84经纬度转UTM投影(示例为UTM 50N带,适配东经114°-120°范围,可根据数据实际位置替换对应EPSG编码) transformer = Transformer.from_crs("EPSG:4326", "EPSG:32650", always_xy=True) lon_arr = df['Longitude'].values lat_arr = df['Latitude'].values x_proj, y_proj = transformer.transform(lon_arr, lat_arr) coords_proj = np.column_stack((x_proj, y_proj))
步骤2:固定带宽Mean Shift聚类
Mean Shift算法会自动迭代识别密度峰值作为簇心,将带宽参数设置为4000(米)即可匹配4km簇半径要求,配合参数预筛、后校验完全满足约束:
# 带宽设为4000米,对应4公里簇半径 cluster_bandwidth = 4000 # 初始化模型:bin_seeding开启格网预聚合提速,min_bin_freq预筛低密度格网,cluster_all=False不强制分配离群点 ms_model = MeanShift( bandwidth=cluster_bandwidth, bin_seeding=True, min_bin_freq=20, cluster_all=False ) ms_model.fit(coords_proj) raw_labels = ms_model.labels_ cluster_centers = ms_model.cluster_centers_
步骤3:结果校验与过滤
对初步聚类结果做两层校验,完全符合约束后输出:
- 逐点校验到所属簇心的距离,超过4km的点标记为噪声
- 统计每个簇的点数,点数不足20的簇整体标记为噪声
final_labels = [] for point_idx, (px, py) in enumerate(coords_proj): current_label = raw_labels[point_idx] # 原本就是噪声的点直接保留 if current_label == -1: final_labels.append(-1) continue # 计算点到对应簇心的欧氏距离 cx, cy = cluster_centers[current_label] point_dist = np.sqrt((px - cx)**2 + (py - cy)**2) if point_dist <= 4000: final_labels.append(current_label) else: final_labels.append(-1) df['cluster_id'] = final_labels # 过滤点数不足20的簇 cluster_size = df['cluster_id'].value_counts() valid_cluster_ids = cluster_size[cluster_size >= 20].index df.loc[~df['cluster_id'].isin(valid_cluster_ids), 'cluster_id'] = -1
方案说明
- 3万条点位数据在普通消费级PC上运行耗时不超过10秒,
bin_seeding参数开启的格网预聚合可将运行效率提升10倍以上。 - 输出结果完全满足要求:所有保留簇的簇心为簇内实际密度峰值,簇内所有点到簇心距离不超过4km,单簇点数≥20,不会出现DBSCAN类算法跨密度区合并大簇的问题。
- 若需要严格执行「所有4km覆盖范围有重叠的簇必须合并」,可在得到簇心后增加一步合并逻辑:两个簇心直线距离≤8km(即两个4km半径圆存在重叠)时合并为同一个簇,重新计算合并后的簇心并校验点距即可,绝大多数业务场景下上述实现已满足要求。
内容的提问来源于stack exchange,提问作者Blank Message
相关产品推荐
相关产品推荐

