IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 【Arcpy】基于相交关系汇集源图层属性值到目标图层目标字段中 -> 正文阅读

[Python知识库]【Arcpy】基于相交关系汇集源图层属性值到目标图层目标字段中

# coding: utf-8

import arcpy
from arcpy import env
import xlrd, random, tempfile, shutil, os

"""
DESC: 
    本段代码用于处理两个图层间属性值关联汇总问题,
    即把源图层的源属性值整合、汇总后填写目标图层的目标属性中。
    至具体包括:
    1、将与目标要素相交的源要素的指定字段值拼接为字符串填写至目标字段;
    2、汇总与目标要素、源要素相交面积并汇总相交面积填写至目标字段;
    3、分类汇总目标要素及源要素相交部分,填写至目标字段。

LOG:
    [0315] 需要解决源、目的图层字段同名后地理处理重命名的问题
    [0316] 已解决,编写__renameField对重名字段做重命名处理
"""


class FieldValueTransfer:

    def __init__(self, workspace, xlsx_path):
        env.workspace = workspace
        env.overwriteOutput = True
        self.xlsx_path = xlsx_path
        
        self.temp_dir = tempfile.mkdtemp()
        self.temp_gdb = os.path.join(self.temp_dir, "temp.gdb")
        arcpy.CreateFileGDB_management(self.temp_dir, "temp.gdb")


    def deleteTempDir(self):
        """
            删除临时文件夹
        """
        shutil.rmtree(self.temp_dir)


    def __layerChecker(self, layer_name):
        """
            检查图层是否存在
            :param layer_name: 图层名
        """
        if not arcpy.Exists(layer_name):
            print "Layer " + layer_name + " not exists!"
            return False
        else:
            return True


    def __fieldCheck(self, layer_name, field_name):
        """
            检查字段是否存在
            :param layer_name: 图层名
            :param field_name: 属性名
        """
        fields_name_list = [f.name for f in arcpy.ListFields(layer_name)]
        if field_name not in fields_name_list:
            print "Field " + field_to + " not exists in Layer " + layer_name + "!"
            return False
        else:
            return True


    def __renameField(self, layer_name, field_name):
        """
            如图层存在字段,对字段重命名
            :param layer: 对比图层
            :param field_name: 原属性名
        """
        field_name_new = field_name
        fields_name_list = [f.name for f in arcpy.ListFields(layer_name)]
        if field_name_new not in fields_name_list:
            return field_name_new
        
        # 生成器
        ext_list = ["_1", "2", "_13", "_14", "_15", "_16", "_17", "_18", "_19"]
        generator_ext = (e for e in ext_list)

        # 逐个判断重命名后的字段是否重名
        while True:
            try:
                ext = next(generator_ext)
                field_name_new += ext
                if field_name_new not in fields_name_list:
                    return field_name_new
            except StopInteration:
                break

        return None


    def sumupFieldValue(self, layer_to, field_to, layer_from, field_from):
        """
            汇总相交要素属性,写入目标要素
            :param layer_to: 写入属性值的图层名
            :param field_to: 写入属性值的字段名
            :param layer_from: 属性值的来源图层
        """
        try:
            # 判断图层/字段是否存在
            if ((not self.__layerChecker(layer_to)) or 
                (not self.__layerChecker(layer_from)) or 
                (not self.__fieldCheck(layer_to, field_to)) or 
                (not self.__fieldCheck(layer_from, field_from))):
                return

            layer_name = "lyr" + str(random.random()*100000)
            arcpy.MakeFeatureLayer_management(layer_from, layer_name)

            # 查找相交并汇总属性
            with arcpy.da.UpdateCursor(layer_to, ("SHAPE@", field_to)) as updateCursor:
                for row_to in updateCursor:
                    geometry_to = row_to[0]
                    arcpy.SelectLayerByLocation_management(layer_name, "INTERSECT", geometry_to)

                    field_value = ""
                    with arcpy.da.SearchCursor(layer_name, ("SHAPE@", field_from)) as searchCursor:
                        for row_from in searchCursor:
                            # 过滤仅边界相邻的
                            geometry_from = row_from[0]
                            if (not geometry_from and
                                not geometry_to and 
                                geometry_to.touches(geometry_from)):
                                continue

                            # 不为空且与其他要素属性值不重复
                            if row_from[1] and len(str(row_from[1]).strip()) > 0 and (str(row_from[1]).strip() not in field_value):
                                field_value += (str(row_from[1]).strip() + unicode("、", "utf-8"))  # unicode编码,解决python中文字符无法连接问题

                        if len(field_value) > 0:
                            field_value = field_value[0:-1]
                            # print field_value
                            row_to[1] = field_value
                            updateCursor.updateRow(row_to)

            arcpy.Delete_management(layer_name)
        except Exception as e:
            print "--- sumupFieldValue ---"
            print arcpy.GetMessages()
            print e


    def sumupIntersectArea(self, layer_to, field_to, layer_from):
        """
            汇总相交图形面积
            :param layer_to: 写入属性值的图层名
            :param field_to: 写入属性值的字段名
            :param layer_from: 属性值的来源图层
        """
        try:
            # 判断图层/字段是否存在
            if ((not self.__layerChecker(layer_to)) or 
                (not self.__layerChecker(layer_from)) or 
                (not self.__fieldCheck(layer_to, field_to))):
                return

            # 相交分析
            output_name = self.temp_gdb + "/" + layer_to + "_" + layer_from + "_Intersect"
            if not arcpy.Exists(output_name):
                arcpy.Intersect_analysis([layer_to, layer_from], output_name, "ALL", "", "")

            # 统计分析
            intable = output_name
            outtable = output_name + "_Statistic"
            statsFields = [["Shape_Area", "SUM"]]
            casefield = "FID_" +  layer_to

            arcpy.Statistics_analysis(intable, outtable, statsFields, casefield)

            # 更新属性值
            with arcpy.da.SearchCursor(outtable, ("FID_" + layer_to, "SUM_Shape_Area")) as searchCursor:
                for srow in searchCursor:
                    expression = "OBJECTID=" + str(srow[0])
                    with arcpy.da.UpdateCursor(layer_to, (field_to), where_clause = expression) as updateCursor:
                        for row_to in updateCursor:
                            row_to[0] = round(srow[1], 2)
                            updateCursor.updateRow(row_to)

        except Exception as e:
            print "--- sumupIntersectArea ---"
            print arcpy.GetMessages()
            print e


    def classifyAndSumupIntersectArea(self, layer_to, field_to, layer_from, field_from):
        """
            分类汇总相交图形面积
            :param layer_to: 写入属性值的图层名
            :param field_to: 写入属性值的字段名
            :param layer_from: 属性值的来源图层
            :param field_from: 属性值的来源字段
        """
        try:
            # 判断图层/字段是否存在
            if ((not self.__layerChecker(layer_to)) or 
                (not self.__layerChecker(layer_from)) or 
                (not self.__fieldCheck(layer_to, field_to)) or 
                (not self.__fieldCheck(layer_from, field_from))):
                return

            # 相交分析
            output_name = self.temp_gdb + "/" + layer_to + "_" + layer_from + "_Intersect"
            if not arcpy.Exists(output_name):
                arcpy.Intersect_analysis([layer_to, layer_from], output_name, "ALL", "", "")

            # 解决数据源属性名在目标土层中已定义问题
            field_from = self.__renameField(layer_to, field_from)
            if not field_from:
                print "Field name " + field_from + " is duplicated in Layer " + layer_to
                return 

            # 统计分析
            intable = output_name
            outtable = output_name + "_Statistic"
            statsFields = [["Shape_Area", "SUM"]]
            casefield = ["FID_" +  layer_to, field_from]

            arcpy.Statistics_analysis(intable, outtable, statsFields, casefield)

            # # 更新属性值
            # with arcpy.da.UpdateCursor(layer_to, ("OBJECTID", field_to)) as updateCursor:
            #     for urow in updateCursor:
            #         expression = "FID_" + layer_to + "=" + str(urow[0])

            #         # 每个要素对应的多行统计结果
            #         with arcpy.da.SearchCursor(outtable, (field_from, "SUM_Shape_Area"), where_clause=expression) as searchCursor:
            #             field_value = ""
            #             for srow in searchCursor:
            #                 srow_field_name = srow[0]
            #                 srow_area = srow[1]
            #                 field_value += (srow_field_name + ": " + str(round(srow_area, 2)) + "㎡、")

            #             # 如果存在多行结果
            #             if len(field_value) > 0:
            #                 field_value = field_value[0:-1][0:255]
            #                 urow[1] = field_value
            #                 updateCursor.updateRow(urow)

            # 更新属性值
            field_value_dict = {}   # 使用字典拼接结果字符串
            with arcpy.da.SearchCursor(outtable, ("FID_" + layer_to, field_from, "SUM_Shape_Area")) as searchCursor:
                for srow in searchCursor:
                    srow_fid = srow[0]
                    srow_field_name = srow[1]
                    srow_area = srow[2]
                    
                    # print srow_field_name
                    if srow_field_name is not None:
                        field_value = (srow_field_name + ": " + str(round(srow_area, 2)) + unicode("㎡、", "utf-8"))
                    else:
                        field_value = ("Null: " + str(round(srow_area, 2)) + unicode("㎡、", "utf-8"))
                    
                    if str(srow_fid) not in field_value_dict:
                        field_value_dict[str(srow_fid)] = field_value
                    else:
                        field_value_dict[str(srow_fid)] += field_value

            for key, val in field_value_dict.items():
                expression = "OBJECTID=" + key
                with arcpy.da.UpdateCursor(layer_to, (field_to), where_clause=expression) as updateCursor:
                    for urow in updateCursor:
                        # print val[0:-1]
                        urow[0] = val[0:-1] # 去掉最后的符号
                        updateCursor.updateRow(urow)

        except Exception as e:
            print "--- classifyAndSumupIntersectArea ---"
            print arcpy.GetMessages()
            print e
    

if __name__ == "__main__":
    try:
        workspace = unicode("C:/Users/may/Desktop/xxxxxx/xxxxxx.gdb", "utf-8")
        xlsx_path = unicode("C:/Users/may/Desktop/xxxxxx/mapper/fieldMapper0316.xlsx", "utf-8")
        # xlsx_path = unicode("C:/Users/may/Desktop/xxxxxx/mapper/fieldMapper0315.xlsx", "utf-8")
        fieldValueTransfer = FieldValueTransfer(workspace, xlsx_path)

        workbook = xlrd.open_workbook(fieldValueTransfer.xlsx_path)
        sheet = workbook.sheet_by_index(0)
        rows = sheet.nrows

        for i in range(1, rows):
            layer_to = sheet.cell(i, 0).value
            field_to = sheet.cell(i, 1).value
            layer_from = sheet.cell(i, 2).value
            field_from = sheet.cell(i, 3).value
            _type = sheet.cell(i, 4).value

            print "\n" + "*" * 20 + str(i) + "*" * 20
            print layer_to, field_to, layer_from, field_from

            if _type == 1.0:
                fieldValueTransfer.sumupFieldValue(layer_to, field_to, layer_from, field_from)
            elif _type == 2.0:
                fieldValueTransfer.classifyAndSumupIntersectArea(layer_to, field_to, layer_from, field_from)
            elif _type == 3.0:
                fieldValueTransfer.sumupIntersectArea(layer_to, field_to, layer_from)
            else:
                continue
        fieldValueTransfer.deleteTempDir()
        print "Done!"

    except Exception as e:
        print e


        

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:06:24  更:2022-03-17 22:07:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 19:24:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码