初始化
This commit is contained in:
201
tools/core/utils/平差工具.py
Normal file
201
tools/core/utils/平差工具.py
Normal file
@@ -0,0 +1,201 @@
|
||||
# 获取每个一级地类面积,主要是12类
|
||||
import arcpy
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from .math_utils import correct_rounding_error
|
||||
|
||||
|
||||
# 获取目标面积
|
||||
def get_area_by_group(dltb_class_feature, excel_target_path, xzqmc, is_by_xzq=False):
|
||||
try:
|
||||
# 读取目标面积Excel文件
|
||||
target_df = pd.read_excel(excel_target_path)
|
||||
|
||||
# 确保列名匹配
|
||||
target_df.columns = target_df.columns.str.strip()
|
||||
|
||||
if is_by_xzq:
|
||||
# 地类编码映射字典
|
||||
land_type_mapping = {
|
||||
'耕地': '01',
|
||||
'园地': '02',
|
||||
'林地': '03',
|
||||
'草地': '04',
|
||||
'其他地类': '12'
|
||||
}
|
||||
|
||||
# 方法1:重命名列后转换为字典
|
||||
df_encoded = target_df.rename(columns=land_type_mapping)
|
||||
result_dict = df_encoded.set_index('行政单位').to_dict('index')
|
||||
|
||||
return result_dict
|
||||
|
||||
# 检查要素类是否存在
|
||||
if not arcpy.Exists(dltb_class_feature):
|
||||
print(f"警告:输入要素类不存在: {dltb_class_feature}")
|
||||
else:
|
||||
# 转为numpy数组供pandas统计使用
|
||||
df = pd.DataFrame(arcpy.da.TableToNumPyArray(dltb_class_feature, ["YJDLBM", "TBDLMJ"], skip_nulls=False, null_value=np.nan))
|
||||
qtdl_df = df[df['YJDLBM'] == '12']
|
||||
if qtdl_df['TBDLMJ'].isnull().any() or qtdl_df['TBDLMJ'].eq(0).any():
|
||||
print("警告:其他地类TBDLMJ字段 存在空值或无效的记录,将不平差其他地类")
|
||||
target_areas = {}
|
||||
else:
|
||||
area_by_group = df.groupby("YJDLBM")["TBDLMJ"].sum()
|
||||
|
||||
for key in area_by_group.keys():
|
||||
area_by_group[key] = area_by_group[key] * 0.0015
|
||||
|
||||
target_areas = area_by_group.to_dict()
|
||||
|
||||
# 获取铁山港区的目标面积
|
||||
gangnan_target = target_df[target_df['行政单位'] == xzqmc]
|
||||
|
||||
if gangnan_target.empty:
|
||||
print(f"警告:未找到{xzqmc}的目标面积数据,将使用TBDLMJ数据进行平差")
|
||||
return target_areas
|
||||
|
||||
# 提取各土地利用类型的目标面积
|
||||
landuse_types = {'01':'耕地', '02':'园地', '03':'林地', '04':'草地', '12':'其他地类'}
|
||||
|
||||
for dlbm, dlmc in landuse_types.items():
|
||||
if dlmc in gangnan_target.columns:
|
||||
if gangnan_target[dlmc].values[0] and not np.isnan(gangnan_target[dlmc].values[0]):
|
||||
target_areas[dlbm] = gangnan_target[dlmc].values[0]
|
||||
|
||||
return target_areas
|
||||
|
||||
except Exception as e:
|
||||
print(f"计算面积时出错: {str(e)}")
|
||||
return {}
|
||||
|
||||
# 按地类平差(全区统一平差)
|
||||
def adjust_area_statistics(stats_df, target_areas):
|
||||
"""
|
||||
根据Excel中的目标面积对统计数据进行平差处理
|
||||
|
||||
Parameters:
|
||||
stats_df: 原始统计数据DataFrame
|
||||
excel_target_path: 包含目标面积的Excel文件路径
|
||||
|
||||
Returns:
|
||||
adjusted_df: 平差后的DataFrame
|
||||
"""
|
||||
try:
|
||||
if target_areas is None:
|
||||
print("警告:目标面积数据为空,不进行平差")
|
||||
return stats_df
|
||||
|
||||
# 准备平差数据
|
||||
adjusted_df = stats_df.copy()
|
||||
if "YJDLBM" not in adjusted_df.columns:
|
||||
dlbm = "YNDLBM"
|
||||
else:
|
||||
dlbm = "YJDLBM"
|
||||
|
||||
adjusted_df['adjusted_area'] = adjusted_df['temp_area']
|
||||
adjusted_df['adjustment_factor'] = 1.0
|
||||
|
||||
# 计算每个地类的原始总面积
|
||||
original_totals = stats_df.groupby(dlbm)['temp_area'].sum().to_dict()
|
||||
|
||||
# 对每个地类进行平差
|
||||
for yjdl, target_area in target_areas.items():
|
||||
if (yjdl in original_totals and original_totals[yjdl] > 0) or target_area > 0:
|
||||
adjustment_factor = target_area / original_totals[yjdl]
|
||||
|
||||
# 应用平差系数
|
||||
mask = adjusted_df[dlbm] == yjdl
|
||||
adjusted_df.loc[mask, 'adjusted_area'] = adjusted_df.loc[mask, 'temp_area'] * adjustment_factor
|
||||
adjusted_df.loc[mask, 'adjustment_factor'] = adjustment_factor
|
||||
|
||||
# 应用误差矫正,确保总和等于目标值
|
||||
adjusted_areas = adjusted_df.loc[mask, 'adjusted_area'].tolist()
|
||||
original_areas = stats_df.loc[mask, 'temp_area'].tolist()
|
||||
corrected_areas = correct_rounding_error(target_area, adjusted_areas, original_areas)
|
||||
adjusted_df.loc[mask, 'adjusted_area'] = corrected_areas
|
||||
|
||||
print(f"地类 {yjdl}: 平差系数 = {adjustment_factor:.6f}, 目标面积 = {target_area}, 矫正后总面积 = {sum(corrected_areas)}")
|
||||
|
||||
return adjusted_df
|
||||
|
||||
except Exception as e:
|
||||
print(f"平差处理失败: {e}")
|
||||
return stats_df
|
||||
|
||||
# 按行政区+地类进行平差
|
||||
def adjust_by_district_landuse(stats_df:pd.DataFrame, target_areas_dict:dict):
|
||||
"""
|
||||
按行政区+地类进行平差
|
||||
|
||||
Parameters:
|
||||
stats_df: 原始统计数据DataFrame
|
||||
target_areas_dict: 目标面积字典,格式:{'行政区': {'地类': 目标面积}}
|
||||
|
||||
Returns:
|
||||
adjusted_df: 平差后的DataFrame
|
||||
"""
|
||||
# 复制原始数据
|
||||
adjusted_df = stats_df.copy()
|
||||
adjusted_df['adjusted_area'] = adjusted_df['temp_area']
|
||||
adjusted_df['adjustment_factor'] = 1.0
|
||||
|
||||
# 获取所有存在的行政区和地类
|
||||
existing_districts = adjusted_df['XZQMC'].unique()
|
||||
|
||||
# 检查目标字典中的行政区是否存在
|
||||
missing_districts = []
|
||||
tt = [td for td in target_areas_dict.keys()]
|
||||
for ed in existing_districts:
|
||||
if ed not in tt:
|
||||
missing_districts.append(ed)
|
||||
|
||||
# 如果有行政区不存在,返回原始数据并提示
|
||||
if missing_districts:
|
||||
print(f"警告:平差数据中不存在行政区: {missing_districts},未进行平差")
|
||||
return stats_df
|
||||
|
||||
# 计算每个行政区每个地类的原始总面积
|
||||
original_totals = stats_df.groupby(['XZQMC', 'YJDLBM'])['temp_area'].sum()
|
||||
|
||||
# 对每个行政区的每个地类进行平差
|
||||
for xzqmc, landuse_targets in target_areas_dict.items():
|
||||
for yjdl, target_area in landuse_targets.items():
|
||||
# 检查该行政区是否有此地类数据
|
||||
if (xzqmc, yjdl) in original_totals.index and original_totals.at[(xzqmc, yjdl)] > 0:
|
||||
adjustment_factor = target_area / original_totals[(xzqmc, yjdl)]
|
||||
|
||||
# 应用平差系数
|
||||
mask = (adjusted_df['XZQMC'] == xzqmc) & (adjusted_df['YJDLBM'] == yjdl)
|
||||
adjusted_df.loc[mask, 'adjusted_area'] = adjusted_df.loc[mask, 'temp_area'] * adjustment_factor
|
||||
adjusted_df.loc[mask, 'adjustment_factor'] = adjustment_factor
|
||||
|
||||
# 应用误差矫正,确保总和等于目标值
|
||||
adjusted_areas = adjusted_df.loc[mask, 'adjusted_area'].tolist()
|
||||
original_areas = stats_df.loc[mask, 'temp_area'].tolist()
|
||||
corrected_areas = correct_rounding_error(target_area, adjusted_areas, original_areas)
|
||||
adjusted_df.loc[mask, 'adjusted_area'] = corrected_areas
|
||||
|
||||
print(f"{xzqmc} - 地类 {yjdl}: 平差系数 = {adjustment_factor:.6f}, 目标面积 = {target_area}, 矫正后总面积 = {sum(corrected_areas)}")
|
||||
|
||||
return adjusted_df
|
||||
|
||||
|
||||
def get_target_areas(excel_path:str, sheet_name:str, xzqmc:str) -> pd.DataFrame:
|
||||
df_excel = pd.read_excel(excel_path, sheet_name)
|
||||
target_df = df_excel[df_excel['行政单位'] == xzqmc]
|
||||
|
||||
df_area_for_merge = target_df.set_index('行政单位').iloc[0].reset_index(name='面积').rename(columns={'index': 'EJDL'})
|
||||
|
||||
return df_area_for_merge
|
||||
|
||||
def get_target_areas_by_group(excel_target_path):
|
||||
# 读取目标面积Excel文件
|
||||
target_df = pd.read_excel(excel_target_path,"Sheet1")
|
||||
|
||||
# 确保列名匹配
|
||||
target_df.columns = target_df.columns.str.strip()
|
||||
|
||||
result_dict = target_df.set_index('行政单位').to_dict('index')
|
||||
|
||||
return result_dict
|
||||
Reference in New Issue
Block a user