利用Arcpy和Geopandas進行多規比對

在ArcGIS中可以很容易進行土規和城規的比對,這裡,利用Arcpy和Geopandas來進行多規比對。

利用Arcpy和Geopandas進行多規比對

利用Arcpy和Geopandas進行多規比對

# encoding: utf-8# @Author : hanqi

資料預處理

匯入相關模組

## 匯入相關模組import arcpyfrom arcpy import envimport numpy as npimport pandas as pdimport geopandas as gpdimport matplotlib。pyplot as plt

防止亂碼

plt。rcParams[‘font。family’] = [‘sans-serif’]plt。rcParams[‘font。sans-serif’] = [‘SimHei’]#替換sans-serif字型為黑體plt。rcParams[‘axes。unicode_minus’] = False # 解決座標軸負數的負號顯示問題

設定arcpy工作環境和路徑

env。workspace = r“F:\ArcGIS\多規對比”path = “F:\ArcGIS\多規對比\圖斑對比。gdb”tg_path = “F:\ArcGIS\多規對比\圖斑對比。gdb\土規用地”cg_path = “F:\ArcGIS\多規對比\圖斑對比。gdb\城規用地”

土規和城規用地分類

讀取資料

land = gpd。GeoDataFrame。from_file(path,layer=‘土規用地’)city = gpd。GeoDataFrame。from_file(path,layer=‘城規用地’)

land。head()city。head()

利用Arcpy和Geopandas進行多規比對

arcpy資料處理

## 刪除欄位## 因為我做過一遍,所以先刪除arcpy。DeleteField_management(tg_path, “tg_yongdi”)arcpy。DeleteField_management(cg_path, “cg_yongdi”)

## 新增欄位fieldName1 = “tg_yongdi”fieldLength = 30# Execute AddField twice for two new fieldsarcpy。AddField_management(tg_path, fieldName1, “TEXT”, field_length=fieldLength)fieldName2 = “cg_yongdi”fieldLength = 30arcpy。AddField_management(cg_path, fieldName2, “TEXT”, field_length=fieldLength)

## 欄位計算器## 城規欄位計算器## 只有一個水域不是建設用地# Set local variablesinTable = cg_pathfieldName = “cg_yongdi”expression = “getClass((!cg_fenlei!))”codeblock = “”“def getClass(cg_fenlei): if cg_fenlei in ”E11“: return ”城規_非建設用地“ else: return ”城規_建設用地“ ”“”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

## 土規欄位計算器# Set local variablesinTable = tg_pathfieldName = “tg_yongdi”expression = “getClass((!Layer!))”codeblock = “”“def getClass(Layer): if Layer in (”TG-一般農田“, ”TG-基本農田“, ”TG-林地“, ”TG-水系“, ”TG-林地“): return ”土規_非建設用地“ if Layer is None: return None else: return ”土規_建設用地“ ”“”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

結果就是上圖,土規和城規的用地分為兩類了,這裡不做演示。

多規比對

## 聯合工具inFeatures = [cg_path, tg_path]outFeatures = outFeatures = path + “\\多規比對”arcpy。Union_analysis (inFeatures, outFeatures, “ALL”)

dg_path = “F:\ArcGIS\多歸對比\圖斑對比。gdb\多規比對”dg = gpd。GeoDataFrame。from_file(path, layer=“多規比對”)dg。head()

利用Arcpy和Geopandas進行多規比對

# Set local variables## 多規欄位計算器inTable = dg_pathfieldName = “cg_yongdi”expression = “getClass3((!cg_yongdi!))”codeblock = “”“def getClass3(cg_yongdi): if cg_yongdi is None: return ”城規_非建設用地“ else: return cg_yongdi”“”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

## 刪除欄位arcpy。DeleteField_management(dg_path, [“FID_城規用地”,“Layer”,“cg_fenlei”,“FID_土規用地”])

## 新增合併欄位fieldName3 = “dg_hebing”fieldLength = 30# Execute AddField twice for two new fieldsarcpy。AddField_management(dg_path, fieldName3, “TEXT”, field_length=fieldLength)

## 城規欄位合併# Set local variablesinTable = dg_pathfieldName = “dg_hebing”expression = “!tg_yongdi!+‘_’+!cg_yongdi!”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”)

dg = gpd。GeoDataFrame。from_file(path, layer=“多規比對”)dg_path = path+‘\\多規比對’dg

利用Arcpy和Geopandas進行多規比對

衝突對比

## 新增索引rec = 0inTable = dg_pathfieldName = “Identify”expression = “autoIncrement()”codeblock = “”“def autoIncrement(): global rec pStart = 1 pInterval = 1 if (rec == 0): rec = pStart else: rec = rec + pInterval return rec ”“”# Execute AddFieldarcpy。AddField_management(inTable, fieldName, “LONG”)# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

dg = gpd。GeoDataFrame。from_file(path, layer=“多規比對”)dg。head()

利用Arcpy和Geopandas進行多規比對

## 按屬性分割# Set local variablesin_feature_class = dg_pathtarget_workspace = pathfields = [‘dg_hebing’]arcpy。SplitByAttributes_analysis(in_feature_class, target_workspace, fields)

cgfjs_tgjs = gpd。GeoDataFrame。from_file(path, layer=“土規_非建設用地_城規_建設用地”)cgfjs_tgjs。plot()

利用Arcpy和Geopandas進行多規比對

cgjs_tgfjs = gpd。GeoDataFrame。from_file(path, layer=“土規_建設用地_城規_非建設用地”)cgjs_tgfjs。plot()

利用Arcpy和Geopandas進行多規比對

區劃調整

土規非建設用地_城規建設用地調整

## 定義路徑tgfjs_cgjs_path = path+“\\土規_非建設用地_城規_建設用地”

# Set local variables## 土地面積大於10000依城規inTable = tgfjs_cgjs_pathfieldName = “gz_1”expression = “getClass((!Shape_Area!))”codeblock = “”“def getClass(Shape_Area): if Shape_Area>10000: return ”依城規用地“ else: return ”依土規用地“ ”“”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

利用Arcpy和Geopandas進行多規比對

利用Arcpy和Geopandas進行多規比對

土規建設用地_城規非建設用地調整

## 限制1000以內不隱藏pd。set_option(‘max_columns’,1000)pd。set_option(‘max_row’,1000)

tgjs_cgfjs_path = path+“\\土規_建設用地_城規_非建設用地”tgjs_cgfjs = gpd。GeoDataFrame。from_file(path, layer=“土規_建設用地_城規_非建設用地”)tgjs_cgfjs。sort_values(‘Shape_Area’,ascending=False) ##觀察面積

利用Arcpy和Geopandas進行多規比對

# Set local variables## 土地面積大於10000以土規inTable = tgjs_cgfjsfieldName = “gz_2”expression = “getClass5((!Shape_Area!))”codeblock = “”“def getClass5(Shape_Area): if Shape_Area>10000: return ”依土規用地“ else: return ”依城規用地“ ”“”# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

tgjs_cgfjs = gpd。GeoDataFrame。from_file(path, layer=“土規_建設用地_城規_非建設用地”)tgjs_cgfjs。plot(column=‘gz_2’,legend=True)

利用Arcpy和Geopandas進行多規比對

資料連線

layerName = dg_pathjoinTable = cgjs_tgfjs_pathjoinField = “Identify”# Join the feature layer to a tablearcpy。AddJoin_management(layerName, joinField, joinTable, joinField)

layerName = ‘多規比對_Layer1’joinTable = cgfjs_tgjs_pathjoinField = “Identify”# Join the feature layer to a tablearcpy。AddJoin_management(layerName, joinField, joinTable, joinField)

## 匯出資料# 輸入in_features = [‘多規比對_Layer1’]# 輸出out_location = path# 執行 FeatureClassToGeodatabasearcpy。FeatureClassToGeodatabase_conversion(in_features, out_location)

dg_3 = gpd。GeoDataFrame。from_file(path, layer=“多規比對_Layer3”)dg_3。head()

利用Arcpy和Geopandas進行多規比對

## 重新命名# Set local variablesin_data = “多規比對_Layer1”out_data = “多規比對_最終”# Execute Renamearcpy。Rename_management(in_data, out_data)

# Set local variablesinTable = path+“\\多規對比_最終”fieldName = “gz_all”expression = “getClass5(!土規_非建設用地_城規_建設用地_gz_1! , !土規_建設用地_城規_非建設用地_gz_2!)” ## 不能用別名codeblock = “”“def getClass6(gz_1,gz_2): if gz_1 is not None: return gz_1 if gz_2 is not None: return gz_2 else: return ”無衝突“ ”“”arcpy。AddField_management(inTable, fieldName, “TEXT”, 30)# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

dg_zz = gpd。GeoDataFrame。from_file(path, layer=“多規比對_最終”)dg_zz。plot(column=‘gz_all’,legend=True)

利用Arcpy和Geopandas進行多規比對

用地判定

就是根據衝突比對來返回想對呀的地塊用地,這裡我用欄位計算pyhton做不出來,用vb可以,但是可以用pandas來處理。 vb指令碼

if [gz_all] = “依土規用地” then value = [多規比對_tg_yongdi]if [gz_all] = “依成規用地” then value = [多規比對_cg_yongdi]if [gz_all] = “無衝突” then value = [多規比對_cg_yongdi]end if

value

pandas

## 最終用地for i in dg_zz。index: if dg_zz。at[i,‘gz_all’]==“無衝突”: dg_zz[“最終用地”]。at[i] = dg_zz[“多規比對_tg_yongdi”]。at[i] if dg_zz。at[i,‘gz_all’] == “依城規用地”: dg_zz[“最終用地”]。at[i] = dg_zz[“多規比對_cg_yongdi”]。at[i] else: dg_zz[“最終用地”]。at[i] = dg_zz[“多規比對_tg_yongdi”]。at[i]dg_zz。head()

## 分列dg_zz[“用地”] = dg_zz[‘最終用地’]。str。split(‘_’,expand=True)[1]dg_zz。head()#dg_zz[“用地”] = s。split(‘_’)[1]

結果,這裡我進行過很多次計算了

利用Arcpy和Geopandas進行多規比對

## 寫入excel檔案dg_zz。to_excel(“成果。xlsx”,index=None,encoding=“utf8”)

然後連接回shp檔案就行了,有些ArcGIS不支援xlsx,儲存的時候可以注意點,我的可以

欄位計算器分列

## 分割欄位# Set local variablesinTable = path + “\\多規比對_最終”fieldName = “yongdi”expression = “getClass6(!zz_yongdi!)” ## 不能用別名codeblock = “”“def getClass6(zz_yongdi): value = zz_yongdi。split(‘_’)[1] return value ”“”arcpy。AddField_management(inTable, fieldName, “TEXT”, 30)# Execute CalculateField arcpy。CalculateField_management(inTable, fieldName, expression, “PYTHON_9。3”, codeblock)

dg_zz = gpd。GeoDataFrame。from_file(path, layer=“多規比對_最終”)dg_zz。plot(column=‘zz_yongdi’,legend=True)

利用Arcpy和Geopandas進行多規比對

成果出圖

fig, ax = plt。subplots(figsize=(10, 10))ax = dg_zz。plot(ax=ax,column=‘yongdi’,cmap=‘Set1’,legend=True,legend_kwds={ ‘loc’: ‘lower left’, ‘title’: ‘圖例’, ‘shadow’: True})plt。suptitle(‘土地利用建設分佈圖’, fontsize=24) # 新增最高級別標題plt。tight_layout(pad=4。5) # 調整不同標題之間間距plt。grid(True, alpha=0。3)fig。savefig(‘土地利用建設分佈圖。png’, dpi=300)

fig, ax = plt。subplots(figsize=(10, 10))ax = dg_zz。plot(ax=ax,column=‘gz_all’,cmap=‘tab10’,legend=True,legend_kwds={ ‘loc’: ‘lower left’, ‘title’: ‘圖例’, ‘shadow’: True})plt。suptitle(‘規劃衝突調整圖’, fontsize=24) # 新增最高級別標題plt。tight_layout(pad=4。5) # 調整不同標題之間間距plt。grid(True, alpha=0。3)fig。savefig(‘規劃衝突調整圖。png’, dpi=300)

利用Arcpy和Geopandas進行多規比對

利用Arcpy和Geopandas進行多規比對