带面积属性的GIS点等面积分组技术实现咨询
实现GIS点按总面积均等分组的方案
Python 实现
这是处理大规模数据最灵活的方案,核心采用贪心近似算法(数据量较大时能快速得到接近均等的分组结果,精度足以满足需求):
- 准备数据:将GIS点的属性表导出为CSV格式(需包含唯一ID和面积字段)
- 编写Python脚本:
import pandas as pd # 读取数据 df = pd.read_csv("points_area.csv") # 计算每组目标总面积 total_area = df["area"].sum() target_per_group = total_area / 20 # 按面积从大到小排序,优先分配大值提升分组均等性 df_sorted = df.sort_values(by="area", ascending=False) # 初始化20个分组 groups = [{"total": 0, "ids": []} for _ in range(20)] for idx, row in df_sorted.iterrows(): # 找到当前总面积最小的分组 min_group = min(groups, key=lambda x: x["total"]) # 将当前点加入该分组 min_group["total"] += row["area"] min_group["ids"].append(row["id"]) # 整理分组结果并关联原数据 group_mapping = [] for group_id, group in enumerate(groups): for point_id in group["ids"]: group_mapping.append({"id": point_id, "group_id": group_id + 1}) group_df = pd.DataFrame(group_mapping) result_df = pd.merge(df, group_df, on="id") # 保存结果 result_df.to_csv("points_grouped.csv", index=False)
- 将分组结果CSV通过唯一ID字段关联回原GIS点要素类,添加
group_id字段即可完成分组。
ArcGIS Desktop 实现
可结合ArcGIS的Python脚本工具完成:
- 步骤1:打开ArcMap/ArcGIS Pro,右键点要素类 -> 导出 -> 表转CSV,导出属性表
- 步骤2:运行上述Python脚本得到分组后的CSV文件
- 步骤3:右键地理数据库 -> 导入 -> 表,将分组CSV导入ArcGIS
- 步骤4:使用连接和关联工具,通过唯一ID字段将分组表与原要素类连接,右键连接后的图层 -> 属性 -> 连接和关联 -> 右键分组表 -> 复制字段,将
group_id字段复制到原要素类 - 步骤5:通过
group_id字段进行分组选择、导出或符号化。
也可直接在ArcGIS中运行适配ArcPy的脚本:
import arcpy fc = "your_point_feature_class" area_field = "area" id_field = "OBJECTID" group_field = "group_id" # 添加分组字段 arcpy.AddField_management(fc, group_field, "SHORT") # 读取所有点的ID和面积 points = [] with arcpy.da.SearchCursor(fc, [id_field, area_field]) as cursor: for row in cursor: points.append({"id": row[0], "area": row[1]}) # 计算目标面积并排序 total_area = sum(p["area"] for p in points) target_per_group = total_area / 20 points_sorted = sorted(points, key=lambda x: x["area"], reverse=True) # 初始化分组并分配点 groups = [{"total": 0, "ids": []} for _ in range(20)] for p in points_sorted: min_group = min(groups, key=lambda x: x["total"]) min_group["total"] += p["area"] min_group["ids"].append(p["id"]) # 更新要素类的分组字段 group_dict = {} for group_id, group in enumerate(groups): for pid in group["ids"]: group_dict[pid] = group_id + 1 with arcpy.da.UpdateCursor(fc, [id_field, group_field]) as cursor: for row in cursor: row[1] = group_dict[row[0]] cursor.updateRow(row)
QGIS 实现
结合Python脚本或图形化工具操作:
- 右键点图层 -> 导出 -> 导出属性表,将属性表导出为CSV
- 运行基础Python脚本得到分组CSV
- 图层 -> 添加图层 -> 添加矢量图层,选择分组CSV导入QGIS
- 打开Processing工具箱 -> 矢量通用 -> 连接属性,通过唯一ID字段将分组表与原点图层连接
- 右键原点图层 -> 属性表 -> 字段计算器,新建字段并赋值为
group_id,将分组字段永久保存到原图层 - 通过
group_id字段进行分组操作。
也可直接在QGIS Python控制台运行适配脚本:
from qgis.core import QgsVectorLayer, QgsField, QgsFeature from PyQt5.QtCore import QVariant layer = iface.activeLayer() area_field = "area" id_field = "fid" group_field = "group_id" # 添加分组字段 layer.startEditing() layer.dataProvider().addAttributes([QgsField(group_field, QVariant.Int)]) layer.updateFields() # 读取点数据 points = [] for feat in layer.getFeatures(): points.append({"id": feat[id_field], "area": feat[area_field]}) # 计算目标面积并排序 total_area = sum(p["area"] for p in points) target_per_group = total_area / 20 points_sorted = sorted(points, key=lambda x: x["area"], reverse=True) # 分组逻辑 groups = [{"total": 0, "ids": []} for _ in range(20)] for p in points_sorted: min_group = min(groups, key=lambda x: x["total"]) min_group["total"] += p["area"] min_group["ids"].append(p["id"]) # 更新图层分组字段 group_dict = {} for group_id, group in enumerate(groups): for pid in group["ids"]: group_dict[pid] = group_id + 1 for feat in layer.getFeatures(): feat[group_field] = group_dict[feat[id_field]] layer.updateFeature(feat) layer.commitChanges()
内容的提问来源于stack exchange,提问作者Spatialised
相关产品推荐
相关产品推荐

