Files
ArcGis_Py/tools/core/acid_stats/行政区划酸化统计表.py
2026-04-22 12:27:49 +08:00

642 lines
27 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
import os
import arcpy
import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.styles import Font
from openpyxl.utils import get_column_letter
from tools.config.arcgis_field_cal_code import codeblock_cal_shfj
from tools.core.utils.excel_utils import ExcelStyleUtils
yjdl_order = ["耕地", "园地", "林地", "草地", "其他"]
ejdl_order = ["水田", "旱地", "水浇地", "果园", "茶园", "橡胶园", "其他园地"]
# --- 2. 辅助函数 ---
# 等级计算
def get_acidification_degree(delta_ph):
"""根据ΔpH值判断酸化程度"""
if pd.isna(delta_ph) or delta_ph == 0:
return "-"
# 请根据您的实际分级标准调整这里的阈值
if delta_ph > 1.0:
return "重度酸化"
elif 0.5 < delta_ph <= 1.0:
return "中度酸化"
elif 0.3 < delta_ph <= 0.5:
return "轻度酸化"
elif 0.1 < delta_ph <= 0.3:
return "弱酸化"
else: # dPH < -0.3
return "其他"
# --- 3. 数据处理与分析 均值---
def process_data_for_table5_7(gdb_path, mean_table_name, sample_table_name):
"""
【最终版 v2】: 增加对制图样点数的处理,以支持加权平均计算。
"""
print("开始处理数据...")
def clean_df(df, columns):
for col in columns:
df[col] = df[col].astype(str).str.strip()
df.replace(['<Null>', 'None', '', '<空>'], np.nan, inplace=True)
df.dropna(subset=columns, inplace=True)
return df
# --- a. 处理样点数据,计算“样点均值” ---
print("--> 步骤1: 计算样点均值...")
sample_table_path = os.path.join(gdb_path, sample_table_name)
sample_fields = ['XZQMC','YJDL','EJDL', 'dPH']
df_samples = pd.DataFrame(arcpy.da.TableToNumPyArray(sample_table_path, sample_fields, 'dPH>0.3', skip_nulls=False))
df_samples = clean_df(df_samples, ['XZQMC','YJDL', 'EJDL'])
# 按 YJDL, EJDL 分组,计算 dPH 的均值
df_sample_means = df_samples.groupby(['XZQMC'])['dPH'].mean().reset_index()
df_sample_means.rename(columns={'dPH': '样点均值'}, inplace=True)
print("样点均值计算完成。")
# --- b. 处理制图数据,获取“制图均值”和“制图样点数” ---
print("--> 步骤2: 获取制图均值和样点数...")
mean_table_path = os.path.join(gdb_path, mean_table_name)
mean_fields = ['XZQMC', 'MEAN', 'COUNT']
df_map_data = pd.DataFrame(arcpy.da.TableToNumPyArray(mean_table_path, mean_fields, skip_nulls=False))
df_map_data = clean_df(df_map_data, ['XZQMC'])
df_map_data.rename(columns={'MEAN': '制图均值', 'COUNT': '制图样点数'}, inplace=True)
print("制图数据获取完成。")
# --- c. 合并数据 ---
print("--> 步骤3: 合并数据...")
df_skeleton = pd.concat([
df_sample_means[['XZQMC']],
df_map_data[['XZQMC']]
]).drop_duplicates().reset_index(drop=True)
df_final = pd.merge(df_skeleton, df_sample_means, on=['XZQMC'], how='left')
# **【核心修改】: 合并整个 df_map_data而不仅仅是均值列**
df_final = pd.merge(df_final, df_map_data, on=['XZQMC'], how='left')
# --- d. 计算酸化程度 ---
print("--> 步骤4: 计算酸化程度...")
# **【核心修改】: 在计算酸化程度之前,先过滤掉不展示的行**
# 我们只对 dPH 在酸化范围内 ( > 0.3) 的数据感兴趣
# 但为了计算合计,我们需要保留所有数据,所以这一步只计算,不删除
df_final['酸化程度_样本'] = df_final['样点均值'].apply(get_acidification_degree)
df_final['酸化程度_制图'] = df_final['制图均值'].apply(get_acidification_degree)
df_final.sort_values(['XZQMC'], inplace=True)
print("数据处理流程完成!")
return df_final
# --- 4. Excel 制表 均值---
def write_to_excel_table5_7(df, output_path):
"""
将处理好的数据写入格式化的 Excel 文件。
"""
if df.empty:
print("警告: 没有数据可以写入 Excel。")
return
print(f"开始生成 Excel 报告到 '{output_path}'...")
wb = Workbook()
ws = wb.create_sheet("Mysheet", 0)
ws.title = "不同土地利用类型pH变化统计"
# --- b. 绘制表头 ---
ws.merge_cells('A1:A2'); ws['A1'] = '乡镇/街道'
ws.merge_cells('B1:E1'); ws['B1'] = 'ΔpH'
ws['B2'] = '样点均值'
ws['C2'] = '酸化程度'
ws['D2'] = '制图均值'
ws['E2'] = '酸化程度'
# --- c. 填充数据 ---
current_row = 3
# **【核心修改】: 先对整个DataFrame进行过滤只保留需要展示的行**
acid_levels_to_show = ["弱酸化", "轻度酸化", "中度酸化", "重度酸化", "其他"]
df_to_write = df[
df['酸化程度_样本'].isin(acid_levels_to_show) | df['酸化程度_制图'].isin(acid_levels_to_show)
].copy() # 使用 .copy() 避免 SettingWithCopyWarning
for _, row_data in df_to_write.iterrows():
print(f"正在写入一级地类...")
# 写入数据”
ws.cell(row=current_row, column=1).value = row_data['XZQMC']
# 填充样点数据
sample_mean = row_data.get('样点均值')
if pd.notna(sample_mean):
ws.cell(row=current_row, column=2).value = f"{sample_mean:.2f}" if sample_mean > 0.3 else "-"
ws.cell(row=current_row, column=3).value = row_data.get('酸化程度_样本', '-') if sample_mean > 0.3 else "-"
else:
ws.cell(row=current_row, column=2).value = "-"
ws.cell(row=current_row, column=3).value = "-"
# 填充制图数据
map_mean = row_data.get('制图均值')
if pd.notna(map_mean):
ws.cell(row=current_row, column=4).value = f"{map_mean:.2f}" if map_mean > 0.3 else "-"
ws.cell(row=current_row, column=5).value = row_data.get('酸化程度_制图', '-') if map_mean > 0.3 else "-"
else:
ws.cell(row=current_row, column=4).value = "-"
ws.cell(row=current_row, column=5).value = "-"
current_row += 1
# --- a. 定义样式 ---
header_font = Font(name='等线', size=11, bold=True)
# --- d. 应用样式和调整列宽 ---
max_col_letter = get_column_letter(ws.max_column)
if current_row > 1: # 确保有数据才应用样式
ExcelStyleUtils.set_style(ws, f'A1:{max_col_letter}{current_row-1}')
ExcelStyleUtils.set_style(ws, f'A1:{max_col_letter}2', header_font)
print("正在自动调整列宽...")
# 设置列宽
ExcelStyleUtils.auto_adjust_column_width(ws)
# --- e. 保存文件 ---
wb.save(output_path)
print("Excel 报告生成成功!")
# --- 2. 数据处理与分析 面积 各乡镇---
def process_data_for_table5_4(gdb_path, area_table_name, target_area_dict):
"""
【最终修正版 v2】: 先建立统一的层级结构,再分别合并统计结果。
"""
print("【最终修正版 v2】开始处理数据...")
def clean_df(df, columns):
for col in columns:
df[col] = df[col].astype(str).str.strip()
df.replace(['<Null>', 'None', '', '<空>'], np.nan, inplace=True)
df.dropna(subset=columns, inplace=True)
return df
# --- a. 独立统计面积数据 ---
print("--> 步骤1: 独立统计面积数据...")
area_table_path = os.path.join(gdb_path, area_table_name)
df_area = pd.DataFrame(arcpy.da.TableToNumPyArray(area_table_path, ['XZQMC', 'SHFJ', 'AREA'], skip_nulls=False))
df_area = clean_df(df_area, ['XZQMC'])
df_final = pd.DataFrame()
if not df_area.empty:
# 计算平差系数
target_shfj_areas = target_area_dict.groupby(['SHFJ'])['AREA_MU'].sum().reset_index()
original_shfj_areas = df_area.groupby(['SHFJ'])['AREA'].sum().reset_index()
original_shfj_areas['AREA_MU'] = original_shfj_areas['AREA'] * 0.0015
adjustment_factors = []
for index, row in original_shfj_areas.iterrows():
shfj = row['SHFJ']
area_mu = row['AREA_MU']
adjustment_factor = target_shfj_areas[target_shfj_areas['SHFJ'] == shfj]['AREA_MU'].values[0] / area_mu
adjustment_factors.append({
'SHFJ': shfj,
'平差系数':adjustment_factor
})
factor_df = pd.DataFrame(adjustment_factors)
df_sh_area = df_area.merge(factor_df[['SHFJ', '平差系数']], on='SHFJ')
df_sh_area['制图面积_亩'] = df_sh_area['AREA'] * 0.0015 * df_sh_area['平差系数']
ts_total_area = df_sh_area.groupby(['XZQMC'])['制图面积_亩'].transform('sum')
df_sh_area['面积占比'] = (df_sh_area['制图面积_亩'] / ts_total_area) * 100
df_area_stats = df_sh_area.pivot_table(
index=['XZQMC'], columns='SHFJ', values=['制图面积_亩', '面积占比'], fill_value=0
).reset_index()
df_area_stats.columns = [f'{col[0]}_{col[1]}'.strip('_') if col[1] else col[0] for col in df_area_stats.columns]
df_final = df_area_stats
print("--> 步骤2: 计算酸化面积合计...")
# 定义属于酸化类别的面积列
acidic_area_cols = [
'制图面积_亩_轻度酸化',
'制图面积_亩_中度酸化',
'制图面积_亩_重度酸化'
]
# 确保这些列存在于DataFrame中不存在的列用0代替
for col in acidic_area_cols:
if col not in df_final.columns:
df_final[col] = 0
# 将这三列相加,得到合计值
df_final['酸化面积合计_亩'] = df_final[acidic_area_cols].sum(axis=1)
# --- d. 最后清理和构建映射 ---
df_final.fillna(0, inplace=True)
print("数据处理流程完成!")
return df_final
# --- 3. Excel 制表 面积---
def write_to_excel_table5_4(df, output_path):
"""
【最终修正版】: 将处理好的数据写入格式化的 Excel 文件。
"""
if df.empty:
print("警告: 没有数据可以写入 Excel将创建一个空的报告。")
wb = Workbook()
ws = wb.create_sheet("Mysheet", 0)
ws.title = "不同乡镇酸化面积统计"
ws['A1'] = "没有有效的统计数据。"
wb.save(output_path)
return
print(f"开始生成 Excel 报告到 '{output_path}'...")
wb = Workbook()
ws = wb.create_sheet("Mysheet", 0)
ws.title = "不同乡镇酸化面积统计"
# --- b. 绘制表头 (不变) ---
ws.merge_cells('A1:A2'); ws['A1'] = '乡镇/街道'
acid_levels = ['弱酸化', '轻度酸化', '中度酸化', '重度酸化', '其他']
# acid_level_headers = ['0.1<ΔpH≤0.3', '0.3<ΔpH≤0.5', '0.5<ΔpH≤1.0', 'ΔpH>1.0', '其他']
# all_possible_levels = ['碱化', '未酸化', '轻度酸化', '中度酸化', '重度酸化']
acid_level_headers = ['弱酸化(0.1<ΔpH≤0.3)','轻度酸化(0.3<ΔpH≤0.5)', '中度酸化(0.5<ΔpH≤1.0)', '重度酸化(ΔpH>1.0)', '其他(未酸化)']
col_start = 2
for header in acid_level_headers:
ws.merge_cells(start_row=1, start_column=col_start, end_row=1, end_column=col_start + 1)
ws.cell(row=1, column=col_start).value = header
ws.cell(row=2, column=col_start).value = '面积/亩'
ws.cell(row=2, column=col_start + 1).value = '占比/%'
col_start += 2
# 增加合计列的表头**
total_col = col_start # 记录合计列的列号
ws.merge_cells(start_row=1, start_column=total_col, end_row=2, end_column=total_col)
ws.cell(row=1, column=total_col).value = '酸化面积合计'
# --- c. 填充数据 (完全重构的逻辑) ---
current_row = 3
# **【核心修改】: 不再需要 group_yl_df直接遍历整个 df**
# 假设 df 已经按 XZQMC 排序(如果需要的话)
df_sorted = df.sort_values('XZQMC').reset_index(drop=True)
for index, row_data in df_sorted.iterrows():
ws.cell(row=current_row, column=1).value = row_data['XZQMC']
col_start = 2
for level in acid_levels:
area_col = f'制图面积_亩_{level}'
area_pct_col = f'面积占比_{level}'
area_val = row_data.get(area_col, 0)
area_pct_val = row_data.get(area_pct_col, 0)
ws.cell(row=current_row, column=col_start).value = f"{area_val:.0f}" if area_val > 0 else "-"
ws.cell(row=current_row, column=col_start + 1).value = f"{area_pct_val:.2f}%" if area_val > 0 else "-"
col_start += 2
# **【核心修改】: 填充酸化面积合计列的值**
total_area_val = row_data.get('酸化面积合计_亩', 0)
ws.cell(row=current_row, column=total_col).value = f"{total_area_val:.0f}" if total_area_val > 0 else "-"
current_row += 1
# **(可选) 增加一个所有乡镇的“总合计”行**
# print("--> 计算并写入总合计行...")
# ws.cell(row=current_row, column=1).value = '总合计'
# col_start = 2
# for level in acid_levels:
# area_col = f'制图面积_亩_{level}'
# area_sum = df_sorted.get(area_col, 0).sum()
# # 总合计行的占比是相对于所有乡镇的总面积
# grand_total_area = df_sorted[[f'制图面积_亩_{lvl}' for lvl in all_possible_levels if f'制图面积_亩_{lvl}' in df_sorted]].sum().sum()
# area_perc = (area_sum / grand_total_area * 100) if grand_total_area > 0 else 0
# ws.cell(row=current_row, column=col_start).value = f"{area_sum:.2f}" if area_sum > 0 else "-"
# ws.cell(row=current_row, column=col_start + 1).value = f"{area_perc:.2f}" if area_sum > 0 else "-"
# col_start += 2
# grand_total_acidic_area = df_sorted['酸化面积合计_亩'].sum()
# ws.cell(row=current_row, column=total_col).value = f"{grand_total_acidic_area:.2f}" if grand_total_acidic_area > 0 else "-"
# current_row += 1
# --- a. 定义样式 (不变) ---
header_font = Font(name='等线', size=11, bold=True)
# --- d. 应用样式和调整列宽 (最终健壮版) ---
max_col_letter = get_column_letter(ws.max_column)
if current_row > 1: # 确保有数据才应用样式
ExcelStyleUtils.set_style(ws, f'A1:{max_col_letter}{current_row-1}')
ExcelStyleUtils.set_style(ws, f'A1:{max_col_letter}2', header_font)
print("正在自动调整列宽...")
# 设置列宽
ExcelStyleUtils.auto_adjust_column_width(ws)
# --- e. 保存文件 ---
wb.save(output_path)
print("Excel 报告生成成功!")
# 步骤5.3: 生成表5.3 - 总表数据处理
def process_data_for_table5_2(gdb_path, area_table_name, sample_table_name, target_area_dict:pd.DataFrame):
def clean_df(df, columns):
for col in columns:
df[col] = df[col].astype(str).str.strip()
df.replace(['<Null>', 'None', '', '<空>'], np.nan, inplace=True)
df.dropna(subset=columns, inplace=True)
return df
# --- a. 从两个表中提取并建立唯一的 (YJDL, EJDL) 层级结构 "骨架" ---
print("--> 步骤1: 建立统一的层级结构...")
sample_table_path = os.path.join(gdb_path, sample_table_name)
area_table_path = os.path.join(gdb_path, area_table_name)
# --- b. 独立统计样点数据 ---
print("--> 步骤2: 独立统计样点数据...")
df_samples = pd.DataFrame(arcpy.da.TableToNumPyArray(sample_table_path, ['XZQMC', 'dPH'], skip_nulls=False))
df_samples = clean_df(df_samples, ['XZQMC'])
if not df_samples.empty:
bins = [-np.inf, 0.1, 0.3, 0.5, 1.0, np.inf]
labels = ["其他", "弱酸化", "轻度酸化", "中度酸化", "重度酸化"]
df_samples['SHFJ'] = pd.cut(df_samples['dPH'], bins=bins, labels=labels, right=True)
sample_counts = df_samples.groupby(['SHFJ'], observed=False).size().reset_index(name='样点数')
sample_counts = sample_counts.merge(df_samples.groupby(['SHFJ'], observed=False)['dPH'].mean(), on='SHFJ')
ts_total_samples = sample_counts['样点数'].sum()
sample_counts['样点占比'] = (sample_counts['样点数'] / ts_total_samples) * 100
# print(sample_counts)
# --- c. 独立统计面积数据 ---
print("--> 步骤3: 独立统计面积数据...")
df_area = pd.DataFrame(arcpy.da.TableToNumPyArray(area_table_path, ['XZQMC', 'SHFJ', 'AREA'], skip_nulls=False))
df_area = clean_df(df_area, ['XZQMC'])
if not df_area.empty:
# 计算平差系数
target_shfj_areas = target_area_dict.groupby(['SHFJ'])['AREA_MU'].sum().reset_index()
original_shfj_areas = df_area.groupby(['SHFJ'])['AREA'].sum().reset_index()
original_shfj_areas['AREA_MU'] = original_shfj_areas['AREA'] * 0.0015
adjustment_factors = []
for index, row in original_shfj_areas.iterrows():
shfj = row['SHFJ']
area_mu = row['AREA_MU']
adjustment_factor = target_shfj_areas[target_shfj_areas['SHFJ'] == shfj]['AREA_MU'].values[0] / area_mu
adjustment_factors.append({
'SHFJ': shfj,
'平差系数':adjustment_factor
})
factor_df = pd.DataFrame(adjustment_factors)
df_sh_area = df_area.merge(factor_df[['SHFJ', '平差系数']], on='SHFJ')
df_sh_area['制图面积_亩'] = df_sh_area['AREA'] * 0.0015 * df_sh_area['平差系数']
df_area_counts = df_sh_area.groupby(['SHFJ'], observed=False)[['制图面积_亩']].sum()
ts_total_area = df_area_counts['制图面积_亩'].sum()
df_area_counts['面积占比'] = (df_area_counts['制图面积_亩'] / ts_total_area) * 100
df_final = pd.merge(sample_counts, df_area_counts, on=['SHFJ'], how='left')
# # --- d. 最后清理和构建映射 ---
df_final.fillna(0, inplace=True)
return df_final
# --- 3. Excel 制表 总表---
def write_to_excel_table5_2(df, df_mean, output_path):
"""
【最终修正版】: 将处理好的数据写入格式化的 Excel 文件。
"""
if df.empty:
print("警告: 没有数据可以写入 Excel将创建一个空的报告。")
wb = Workbook()
ws = wb.create_sheet("Mysheet", 0)
ws['A1'] = "没有有效的统计数据。"
wb.save(output_path)
return
print(f"开始生成 Excel 报告到 '{output_path}'...")
wb = Workbook()
ws = wb.create_sheet("Mysheet", 0)
ws.title = "行政区酸化程度等级分布及占比"
# --- b. 绘制表头 (不变) ---
ws.merge_cells('A1:B1'); ws['A1'] = '酸化程度'
ws.merge_cells('C1:D1'); ws['C1'] = '样点统计'
ws.merge_cells('E1:F1'); ws['E1'] = '制图统计'
ws.merge_cells('A8:B8'); ws['A8'] = '总计'
ws.merge_cells('A9:B9'); ws['A9'] = '全县酸化样点ΔpH 均值'
ws.merge_cells('A10:B10'); ws['A10'] = '全县酸化制图ΔpH 均值'
ws['A2'] = '分级'; ws['B2'] = '值域'
ws['C2'] = '数量/个'; ws['D2'] = '占比'
ws['E2'] = '面积/亩'; ws['F2'] = '占比'
acid_levels = ['弱酸化', '轻度酸化', '中度酸化', '重度酸化', '其他']
acid_level_headers = ['0.1<ΔpH≤0.3', '0.3<ΔpH≤0.5', '0.5<ΔpH≤1.0', 'ΔpH>1.0', '未酸化']
# --- c. 填充数据 ---
current_row = 3
# 1. 遍历该一级地类下的所有“二级地类”并写入数据
for index,level in enumerate(acid_levels):
ws.cell(row=current_row, column=1).value = level
ws.cell(row=current_row, column=2).value = acid_level_headers[index]
# 在子集中查找当前二级地类的数据行
row_data = df[df['SHFJ'] == level]
# --- 填充单元格的逻辑开始 ---
col_start = 3 # 从第 C 列开始填充
# 检查是否找到了该土属的数据
if not row_data.empty:
data_series = row_data.iloc[0]
# 1. 构建要从 data_series 中查找的列名
sample_col = f'样点数'
sample_pct_col = f'样点占比'
area_col = f'制图面积_亩'
area_pct_col = f'面积占比'
# 2. 从 data_series 中安全地获取值
sample_val = data_series.get(sample_col, 0)
sample_pct_val = data_series.get(sample_pct_col, 0)
area_val = data_series.get(area_col, 0)
area_pct_val = data_series.get(area_pct_col, 0)
# 3. 将获取到的值填入单元格
ws.cell(row=current_row, column=col_start).value = f"{sample_val:.0f}" if sample_val > 0 else "-"
# 占比/%
ws.cell(row=current_row, column=col_start + 1).value = f"{sample_pct_val:.2f}%" if sample_val > 0 else "-"
# 制图面积/亩
ws.cell(row=current_row, column=col_start + 2).value = f"{area_val:.0f}" if area_val > 0 else "-"
# 占比/%
ws.cell(row=current_row, column=col_start + 3).value = f"{area_pct_val:.2f}%" if area_val > 0 else "-"
# 移动到下一个酸化等级的起始列
col_start += 2
else:
for _ in range(4):
ws.cell(row=current_row, column=col_start).value = "-"
col_start += 1
current_row += 1
# 合计单元格填充
mask = df["SHFJ"].isin(acid_levels)
df_acid = df[mask]
weighted_avg = (df_acid["dPH"] * df_acid["样点数"]).sum() / df_acid["样点数"].sum()
mean_msk = df_mean["酸化程度_制图"].isin(acid_levels)
df_mean_acid = df_mean[mean_msk]
weighted_mean = (df_mean_acid["制图均值"] * df_mean_acid["制图样点数"]).sum() / df_mean_acid["制图样点数"].sum()
ws.merge_cells('C9:F9')
ws.merge_cells('C10:F10')
ws['C8'] = df[df['SHFJ'].isin(acid_levels)]['样点数'].sum()
ws['D8'] = f"{df[df['SHFJ'].isin(acid_levels)]['样点占比'].sum():.2f}%"
ws['E8'] = f"{df[df['SHFJ'].isin(acid_levels)]['制图面积_亩'].sum():.0f}"
ws['F8'] = f"{df[df['SHFJ'].isin(acid_levels)]['面积占比'].sum():.2f}%"
ws['C9'] = f"{weighted_avg:.2f}" # type: ignore
ws['C10'] = f"{weighted_mean:.2f}"
# --- a. 定义样式 (不变) ---
header_font = Font(name='宋体', size=11)
# --- d. 应用样式和调整列宽 (最终健壮版) ---
if current_row > 1: # 确保有数据才应用样式
ExcelStyleUtils.set_style(ws, f'A1:F10')
ExcelStyleUtils.set_style(ws, f'A1:F2', header_font)
print("正在自动调整列宽...")
# 设置列宽
ExcelStyleUtils.auto_adjust_column_width(ws)
# --- e. 保存文件 ---
wb.save(output_path)
print("Excel 报告生成成功!")
def main(gdb_path, xzq_features, ph_features, dltb_features, sh_ph_tif, output_path,target_areas_dict:dict):
try:
# --- 1. 用户配置 ---
# 输出配置
output_excel_path = os.path.join(output_path,"乡镇街道酸化统计表.xlsx") # 生成的Excel报告文件路径
# 设置工作空间和变量
arcpy.env.workspace = gdb_path
arcpy.env.overwriteOutput = True
sample_table_name = "历史样点PH信息_Table" # 图2: 样点信息表名
in_zone_feature = xzq_features # 规划分区图层
in_class_feature = ph_features # 已重分类好的酸化PH图层
dltb_class_feature = dltb_features
in_value_raster = sh_ph_tif # 赋值栅格
out_feature_class = "最小面积统计单元"
out_table_area = r"行政区划_酸化面积表" # 输出的交集表名
out_table_mean = r"行政区划_酸化均值表" # 输出的均值表名
print("开始处理数据...")
if not arcpy.Exists(out_feature_class):
# 判断输入表是否存在SHFJ字段
try:
arcpy.management.CalculateField(in_class_feature, "SHFJ", "calculate_shfj(!gridcode!)", "PYTHON3", codeblock_cal_shfj)
except Exception as e:
print(f"计算SHFJ字段时发生错误: {e}")
arcpy.analysis.Intersect(
in_features=[dltb_class_feature, in_class_feature],
out_feature_class=out_feature_class,
join_attributes="ALL",
output_type="INPUT"
)
if not arcpy.Exists(out_table_area):
# 1.用arcpy.analysis.TabulateIntersection进行交集制表
arcpy.analysis.TabulateIntersection(
in_zone_feature,
["XZQMC"],
out_feature_class,
out_table_area,
"SHFJ",
out_units="SQUARE_METERS",
)
if not arcpy.Exists(out_table_mean):
# 2.用arcpy.sa.ZonalStatisticsAsTable进行区域统计
arcpy.sa.ZonalStatisticsAsTable(
in_zone_feature, "XZQMC", in_value_raster, out_table_mean, "DATA", "MEAN"
)
# 计算按地类平差后的各酸化等级面积
if arcpy.Exists(out_feature_class):
df = pd.DataFrame(arcpy.da.TableToNumPyArray(out_feature_class, ["YJDL", "SHFJ", "Shape_Area"]))
df_area = df.groupby(["YJDL", "SHFJ"]).agg({"Shape_Area": "sum"}).reset_index()
yjdl_area = df_area.groupby(['YJDL'])['Shape_Area'].sum().reset_index()
landuse_types = {'耕地':'01', '园地':'02', '林地':'03', '草地':'04', '其他':'12'}
adjustment_factors = []
for _, row in yjdl_area.iterrows():
yjdl = row['YJDL']
original_total = row['Shape_Area'] * 0.0015
target_total = target_areas_dict.get(landuse_types[yjdl], original_total)
adjustment_factor = target_total / original_total
adjustment_factors.append({
'YJDL': yjdl,
'平差系数': adjustment_factor
})
factor_df = pd.DataFrame(adjustment_factors)
df_with_factors = df_area.merge(factor_df[['YJDL', '平差系数']], on='YJDL')
df_with_factors['AREA_MU'] = df_with_factors['Shape_Area'] * df_with_factors['平差系数'] * 0.0015
# print(df_with_factors)
# 生成表5.4的面积统计Excel报告
final_area_dataframe = process_data_for_table5_4(gdb_path, out_table_area, df_with_factors)
write_to_excel_table5_4(final_area_dataframe, output_excel_path)
# 生成表5.3的均值统计Excel报告
final_mean_dataframe = process_data_for_table5_7(gdb_path, out_table_mean, sample_table_name)
write_to_excel_table5_7(final_mean_dataframe, output_excel_path.replace(".xlsx", "_mean.xlsx"))
# 生成总表5.2的统计Excel报告
final_dataframe = process_data_for_table5_2(gdb_path, out_table_area, sample_table_name, df_with_factors)
write_to_excel_table5_2(final_dataframe, final_mean_dataframe, output_excel_path.replace(".xlsx", "_total.xlsx"))
return df_with_factors
except Exception as e:
print(f"\n处理过程中发生严重错误: {e}")
import traceback
traceback.print_exc()
finally:
import gc
gc.collect()
# --- 4. 主程序入口 ---
# if __name__ == "__main__":
# main()