基於ArcGIS的python編程 9.python操作Excel與屬性表批處理

這裡先說一下上一篇文章最後留下的那個問題:把點坐標文檔里的點的順序打亂了,最後能不能生成面?去嘗試了一下,結果是不行的,說明Arcpy中點構面也有一定的順序的,所以隨便不能搞混點的位置。搞混點順序生成的面如圖1所示 是一個不能生成完整的面。

圖1

上周六早上還在夢鄉的我被一個信息吵醒,睜開朦朧的眼睛起來一看,居然是小仙女 向我尋求幫助,說工作很急很急!她正在弄地名普查的數據檢查工作,叫我幫她弄一個程序;雖然很困,但是想到對面的小仙女那麼著急,有點不忍心拒絕,然後我二話不說打開電腦,來不及洗漱,餓著肚子在電腦面前擼起了代碼……經過一個多小時的努力,終於基本完成了小仙女的需求,然後迫不及待的把代碼發給小仙女,懷著期待的心情,等待著小仙女的回復,等來的卻是:「我已經弄完了!」這時我的心情是多麼的……

現在有空總結一下上周六尷尬的事情,一個簡單的小程序居然弄了一個多小時,確實有點慢,那麼菜,還得繼續好好修鍊啊。那麼慢的另一個原因就是對小仙女的需求了解不夠,手上也沒調試的數據,對那個數據表的結構不清楚等等,這些都要邊敲代碼邊去詢問;另外,當時太過於興奮,沒有把思路弄清楚就去盲目敲代碼,導致後面的代碼要改來改去。所以要吸取經驗教訓,凡事都要先弄清楚需求,需求是我們的工作的方向標,需求清楚後再去把思路弄清楚,最後才是通過代碼去實現需求。

之後小仙女也跟我分享了他們的解決方法,他們是用 屬性表關聯+欄位運算 完成的;那時就像發現了新大陸,原理屬性表關聯還有那麼厲害的功能。反正條條大路通羅馬,解決問題的辦法不止一種,適合自己的才是最好的方法。屬性表關聯的詳細過程到時可以參考小仙女的分享。

下面我就說說我的解決方案吧!

言歸正傳,先說說小仙女的需求:三個圖層(地名點,鎮區面,村域面)和一個地名Excle表格;先在Excel表格里找出重複的地名,然後在地名點圖層找到該重複的地名點,補充完整這些地名點的屬性表信息,其中鎮名欄位就是地名點所在鎮區的名字,村名欄位就是地名點所在村的名字,最後把該地名名稱改為:村名+地名。

獲得Excel表格中重複的地名

python操作excel表格需要先安裝第三方類庫xlrd,xlrd庫只能操作97-2003版本的(.xls)(經過後面的實驗驗證,xlrd可以同時操作.xls或者.xlsx版本的表格);然後就可以調用該類庫的函數去操作Excel,獲得我們需要的信息。地名都位於第一列,所以讀取相對簡單點(如圖2)

圖2 地名表

代碼如下:

#coding=utf-8nimport xlrdnimport arcpynndef getpointNameList(Exclepath):n PointNameList=[]n #excle表格格式要為.xlsn data=xlrd.open_workbook(Exclepath) #打開excle表格n table=data.sheets()[0] #獲得Excel里的第一張表n nameList=table.col_values(0) #獲得第一列(地名),為列表格式n n #在nameList中查找查找重複的點名n for name in nameList:n if nameList.count(name)>1:n PointNameList.append(name) #獲得的是所有重複值n n PointNameList = list(set(PointNameList)) #在重複值列表中去重n return PointNameListn

完善點圖層的屬性信息

因為我手上也沒有調試數據,所以根據小仙女的需求,簡單的構建了測試數據需要的欄位,數據的屬性表如下圖3,4,5,6

圖3 測試數據

圖4 地名點圖層屬性表

圖 5 村域圖層屬性表

圖 6 鎮區屬性表

欄位名稱,表格名稱盡量不要用中文吧,因為python2對中文兼容性不好,剛剛開始我用中文是也報錯了

利用getpointNameList()函數的返回值在點圖層里找到對應的點,然後分別利用該點去與鎮區、村域圖層進行位置關係的判斷(這裡是利用contains函數),如果點在面中,就獲取鎮名,村名寫入到點圖層屬性表相應的欄位中,最後更改地名點的名稱。

def WriteAttribute(PointNameList,pointpath,zhenpath):n for name in PointNameList: #遍歷地名列表n pointCursor = arcpy.UpdateCursor(pointpath) # 點數據更新游標n for pointrow in pointCursor:n pointGeo=pointrow.shape #獲得點的幾何圖形nn if pointrow.PointName==name: #判斷點名是否相等n zhenCursor = arcpy.SearchCursor(zhenpath) # 鎮區的搜索游標n for zhenrow in zhenCursor: #循環判斷點是否在面中n zhenGeo=zhenrow.shapen if(zhenGeo.contains(pointGeo)):n pointrow.zhenName=zhenrow.zhenName #如果在面中,獲得該面的鎮名並填入點屬性表中nn cunCursor = arcpy.SearchCursor(cunpath)n for cunrow in cunCursor:n cunGeo = cunrow.shapen if (cunGeo.contains(pointGeo)):n pointrow.cunName = cunrow.cunNamen pointrow.PointName = cunrow.cunName + namenn pointCursor.updateRow(pointrow)n

存入相應的參數,調用上面兩個函數,就基本完成了小仙女提出的需求了。

程序運行後的結果如圖7所示。對比圖4的表,我們可以看到PointName,zhenName,cunName這三個欄位已經更新了。至於有些地名點沒有更新,是因為我在構建Excel表格時故意沒有讓它重複,所以它就被排除在外,不用更新了。

更新後的屬性表

總結:

最後自己調試才發現自己上周六寫的程序錯漏百出,是多麼的爛,幸好那天小仙女沒有把希望都寄托在我的爛程序上,要不然就尷尬了。技術不過關,還是不要去丟人現眼了,好好修鍊。

這篇文章中用到的函數功能前面的文章都有涉及,無非就是三個游標的使用,幾何圖形的空間位置的判斷等。加入一個新的內容就是xlrd類庫的應用,對於這個類庫的詳細使用這裡就不再闡述,網上有很多相關的教程,仔細去看還是可以看懂的。

據我了解現在GIS行業比較多的項目都是地名普查,不動產登記,土地確權,三調等數據量比較大的項目,所以對於數據批處理的需求也很大。所以覺得python在當中將會發揮著巨大的作用,因為python有豐富的第三方類庫,幾乎需要什麼功能你都能找到對應的類庫,然後去調用簡單的函數就能實現你需要的功能,這樣對於數據處理幫助很大。比如說這裡的xlrd。

歡迎大家一起交流,一起學習,一起進步!


推薦閱讀:

Awesome GIS(GIS Tech Stack技術棧)
為什麼cityengine中文版教程這麼少?cityengine相比其他建模軟有什麼優勢?
中國最牛的gis人員每天的生活是什麼樣的?

TAG:ArcGIS | GIS地理信息系统 | GIS软件工程师 |