用python處理arcgis導出的地類excel表

算是雜記,經常在微信里看到9塊9學python處理excel,一直沒機會。正好最近有個本科室友找我,問能不能給他處理個工程測算表,指明了要用python來做。本科的鐵哥們,這忙咱得幫。說干就干,首先當然是不去報班買9塊9的課程。

首先,看看要處理的表是啥樣,他想要的處理結果是啥樣

老鐵做測量多年,用excel表滑溜的很,他是為了報單位的創新項目,所以才想用python提高一下科技含量。他對自己要處理的表和處理成啥樣了然于心。
原表是一張arcgis導出的各地類的測量面積表,里面有上千個圖斑,也就對應著上千條記錄。要處理成一張匯總表,根據項目、鎮界統計各地類的面積。看著不算難,但是各類統計以及按格式填表,著實讓我忙活了一陣。

以下為原始數據表:

arcgis導出表.png

統計匯總表:

成果匯總表.png

可以從匯總表中看到,統計分兩個維度,一個是根據項目及鎮、村來統計各地類的總面積,還有一個維度是統計該區域內各地類的總面積。

高效統計法推薦

這里不得不提到一個python庫——pandas,能夠像操作數據庫那樣進行分組操作。

data_arcgis = pd.read_excel(inputfile, inputsheetname)
grp1 = data_arcgis.groupby(['權屬', '鎮界', '界線', 'DLMC', '地類', '分區']).agg({'畝': ['sum']}).reset_index()

通過權屬、鎮界、地類等對原始數據進行最小粒度的分組,這樣操作就能獲得最小粒度數據,為后面的匯總打下數據基礎

grp3 = grp2.groupby(['鎮界'])
Town_list = list(grp3.groups.keys())  ###獲取鎮界枚舉值

通過該方法獲得組內的枚舉值,為寫入匯總表里的鎮、村準備數據源

    for town in Town_list:
        grp4 = grp2[grp2['鎮界'] == town]
        grp5 = grp4.groupby(['分區'])
        Fq_list = list(grp5.groups.keys())   ###獲取分區枚舉值
        town_total = grp4.agg({'畝': ['sum']}).reset_index()['畝'].iloc[0,0]
        #print(town + ':' + str(town_total))
        sheet.cell(row = startrowindex + lineindex, column=4).value = town
        sheet.cell(row = startrowindex + lineindex, column=4).font = font
        sheet.cell(row = startrowindex + lineindex, column=8).value = town_total
        sheet.cell(row = startrowindex + lineindex, column=8).font = font
        lineindex = lineindex + 1
        for fq in Fq_list:
            grp6 = grp4[grp4['分區'] == fq]
            grp7 = grp6.groupby(['界線'])
            Jx_list = list(grp7.groups.keys())   ###獲取界線枚舉值
            for jx in Jx_list:
                grp8 = grp6[grp6['界線'] == jx]
                grp9 = grp8.groupby(['地類'])
                Dl_list = list(grp9.groups.keys())   ###獲取地類枚舉值
                jx_total = grp6[grp6['界線'] == jx].agg({'畝': ['sum']}).reset_index()['畝'].iloc[0,0]
                #print('    ' + fq + ':' + jx + ':' + str(jx_total)) 
                sheet.cell(row = startrowindex + lineindex, column=2).value = fq
                sheet.cell(row = startrowindex + lineindex, column=2).font = font
                sheet.cell(row = startrowindex + lineindex, column=5).value = jx
                sheet.cell(row = startrowindex + lineindex, column=5).font = font
                sheet.cell(row = startrowindex + lineindex, column=8).value = jx_total
                sheet.cell(row = startrowindex + lineindex, column=8).font = font
                for dl in Dl_list:
                    dl_total = grp8[grp8['地類'] == dl].agg({'畝': ['sum']}).reset_index()['畝'].iloc[0,0]
                    dic_dl_value[dl] = dic_dl_value[dl]  + dl_total
                    total_sum = total_sum + dl_total
                    sheet.cell(row = startrowindex + lineindex, column=dic_dl_column[dl]).value = dl_total
                    sheet.cell(row = startrowindex + lineindex, column=dic_dl_column[dl]).font = font
                    #print('        ' + dl + ':' + str(dl_total)) 
                lineindex = lineindex + 1

依次遍歷鎮界、分區、界線、地類,最后在地類循環中,對相同地類進行累計求和。至此就可以獲得相應鎮界、分區、界線下的地類匯總面積,同時通過lineindex來計算寫入的行號,保證了運算結果寫入到爭取的行列內。

令人頭疼的難點

方法不難,最頭疼的還是原始數據的不規范帶來的不必要的程序消耗。因為原始數據中地類寫入的隨意性,以及新增臨時地類(即不在匯總表內的地類),則需要進行額外的處理。
處理原則是,只要原始數據中地類名稱有和匯總表內的字段名相匹配的,則認為命中,記錄下該字段在excel中的列號,如果不在,則放入匯總表內的最后列。程序跑完后,由人工介入處理。

def setDlcolumn(all_dl_list, dl_type_series, dic_dl_column):
    dl_column_length = dl_type_series.shape[0]
    dl_column_length_bak = dl_column_length
    for dl_target in all_dl_list:
        colum_index = 0
        flag = 0
        for dl_type in dl_type_series.array:
            colum_index = colum_index + 1
            if str(dl_type) == 'nan':
                continue
            if dl_target in dic_dl_column and dic_dl_column[dl_target] < dl_column_length_bak: ###字典里已存在該地類
                flag = 1
                break
            if dl_target in dl_type:   ###如果arcgis中地類包含在樣表中,則記錄下列號
                flag = 1
                dic_dl_column[dl_target] = colum_index
                break
        if flag == 0:
            dl_column_length = dl_column_length + 1
            dic_dl_column[dl_target] = dl_column_length
    return dic_dl_column

處理效果

程序輸出結果表.png

最后輸出的結果,數值和統計結果一致,樣式上還有所欠缺,需要利用openpyxl對表格進行樣式修飾。基本達到老鐵預期。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。