用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对表格进行样式修饰。基本达到老铁预期。

你可能感兴趣的:(用python处理arcgis导出的地类excel表)