Files
YunNanProject/Model/RuYuanZaiYuanCountModel.py
2025-09-12 21:31:45 +08:00

309 lines
15 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.

import json
import os
from Util.YuCeUtil import YuCeUtil
class RuYuanZaiYuanModel:
# 定义支持的教育阶段映射
EDUCATION_STAGES = {
'preschool': '学前',
'primary': '小学',
'junior': '初中',
'senior': '高中',
'vocational': '中职'
}
@staticmethod
def load_student_data():
try:
# 加载招生数据(入园人数)
with open("./Data/ZhaoShengCount.json", "r", encoding="utf-8") as f:
enrollment_data = json.load(f)
# 加载在校生数据(在园人数)
with open("./Data/ZaiXiaoShengCount.json", "r", encoding="utf-8") as f:
in_school_data = json.load(f)
return enrollment_data, in_school_data
except Exception as e:
print(f"读取学生数据出错: {e}")
return [], []
@staticmethod
def generate_preschool_education_config(education_stage='preschool', area_name='云南省'):
# 验证教育阶段参数
if education_stage not in RuYuanZaiYuanModel.EDUCATION_STAGES:
education_stage = 'preschool' # 默认使用学前
# 获取学前教育相关数据
enrollment_data, in_school_data = RuYuanZaiYuanModel.load_student_data()
# 提取指定区域数据
area_enroll = next((item for item in enrollment_data if item["area_name"] == area_name), None)
if not area_enroll:
return {}
# 构建学前教育数据
urban_data = [] # 城区数据
town_data = [] # 镇区数据
rural_data = [] # 乡村数据
total_enroll = [] # 总人数
# 提取年份数据(2015-2035)
years = [str(year) for year in range(2015, 2036)]
# 初始化预测工具(只针对学前教育进行预测)
forecast_util = None
forecast_results = {}
forecast_urban_enrollment = {}
if education_stage == 'preschool':
# 获取数据目录
data_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'Data')
# 创建预测实例,使用传入的区域名称
forecast_util = YuCeUtil(data_directory, area_name)
# 运行预测
forecast_util.run_forecast()
# 获取预测结果
forecast_results = forecast_util.forecast_results
forecast_urban_enrollment = forecast_util.forecast_urban_enrollment
for year in years:
# 使用传入的教育阶段参数
if int(year) <= 2024:
# 2015-2024年使用实际数据
enroll_data = area_enroll["education_data"].get(education_stage, {}).get(year, {})
# 特殊处理中职数据格式只有total字段
if education_stage == 'vocational':
total_value = enroll_data.get("total", 0)
urban_data.append(0) # 中职没有城区数据
town_data.append(0) # 中职没有镇区数据
rural_data.append(0) # 中职没有乡村数据
total_enroll.append(total_value / 10000) # 转换为万人
else:
urban_data.append(enroll_data.get("urban", 0) / 10000) # 转换为万人
town_data.append(enroll_data.get("town", 0) / 10000) # 转换为万人
rural_data.append(enroll_data.get("rural", 0) / 10000) # 转换为万人
# 计算总和作为总人数
calculated_total = enroll_data.get("urban", 0) + enroll_data.get("town", 0) + enroll_data.get("rural", 0)
total_enroll.append(calculated_total / 10000) # 转换为万人
else:
# 2025-2035年使用预测数据
if education_stage == 'preschool' and forecast_util:
if year in forecast_results:
total_value = forecast_results[year]
# 获取城区招生数
urban_value = forecast_urban_enrollment.get(int(year), {}).get('urban', 0)
remaining_value = total_value - urban_value
# 假设乡镇和农村按历史比例分配剩余部分
# 查找最近一年的乡镇和农村比例
recent_year = str(int(year) - 1)
if recent_year in area_enroll["education_data"].get(education_stage, {}):
recent_data = area_enroll["education_data"].get(education_stage, {}).get(recent_year, {})
recent_town = recent_data.get("town", 0)
recent_rural = recent_data.get("rural", 0)
recent_remaining = recent_town + recent_rural
if recent_remaining > 0:
town_value = int(remaining_value * (recent_town / recent_remaining))
rural_value = remaining_value - town_value
else:
town_value = int(remaining_value / 2)
rural_value = remaining_value - town_value
else:
town_value = int(remaining_value / 2)
rural_value = remaining_value - town_value
urban_data.append(urban_value / 10000)
town_data.append(town_value / 10000)
rural_data.append(rural_value / 10000)
total_enroll.append(total_value / 10000)
else:
# 没有预测数据,使用前一年数据
if len(total_enroll) > 0:
urban_data.append(urban_data[-1])
town_data.append(town_data[-1])
rural_data.append(rural_data[-1])
total_enroll.append(total_enroll[-1])
else:
urban_data.append(0)
town_data.append(0)
rural_data.append(0)
total_enroll.append(0)
else:
# 非学前教育或没有预测工具,使用前一年数据
if len(total_enroll) > 0:
urban_data.append(urban_data[-1])
town_data.append(town_data[-1])
rural_data.append(rural_data[-1])
total_enroll.append(total_enroll[-1])
else:
urban_data.append(0)
town_data.append(0)
rural_data.append(0)
total_enroll.append(0)
# 添加2022年基数的粉色折线
base_year = "2022"
# 找到2022年在years中的索引位置
base_index = years.index(base_year) if base_year in years else 0
# 获取2022年的总人数作为基数
base_value = total_enroll[base_index] if base_index < len(total_enroll) else 0
# 创建2022年基数折线数据2022-2035年
base_2022_line = []
for i, year in enumerate(years):
# 只在2022年及之后显示基数线
if i >= base_index:
base_2022_line.append(base_value)
else:
base_2022_line.append(None) # 2022年之前不显示
data = {
"xAxis_data": years,
"series_data_0": urban_data, # 城区
"series_data_1": town_data, # 镇区
"series_data_2": rural_data, # 乡村
"series_data_3": total_enroll, # 总人数
"series_data_4": base_2022_line, # 2022年基数
"education_stage": RuYuanZaiYuanModel.EDUCATION_STAGES.get(education_stage, '学前') # 添加教育阶段名称
}
return data
@staticmethod
def generate_in_school_education_config(education_stage='preschool', area_name='云南省'):
# 验证教育阶段参数
if education_stage not in RuYuanZaiYuanModel.EDUCATION_STAGES:
education_stage = 'preschool' # 默认使用学前
# 获取在校生相关数据
enrollment_data, in_school_data = RuYuanZaiYuanModel.load_student_data()
# 提取指定区域数据
area_in_school = next((item for item in in_school_data if item["area_name"] == area_name), None)
if not area_in_school:
return {}
# 构建在校生数据
urban_data = [] # 城区数据
town_data = [] # 镇区数据
rural_data = [] # 乡村数据
total_in_school = [] # 总人数
# 提取年份数据(2015-2035)
years = [str(year) for year in range(2015, 2036)]
# 初始化预测工具(只针对学前教育进行预测)
forecast_util = None
enrollment_in_school = {}
if education_stage == 'preschool':
# 获取数据目录
data_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'Data')
# 创建预测实例,使用传入的区域名称
forecast_util = YuCeUtil(data_directory, area_name)
# 运行预测
forecast_util.run_forecast()
# 获取预测结果
enrollment_in_school = forecast_util.enrollment_in_school
for year in years:
# 使用传入的教育阶段参数
if int(year) <= 2024:
# 2015-2024年使用实际数据
in_school_year_data = area_in_school["student_data"].get(education_stage, {}).get(year, {})
# 特殊处理中职数据格式只有total字段
if education_stage == 'vocational':
total_value = in_school_year_data.get("total", 0)
urban_data.append(0) # 中职没有城区数据
town_data.append(0) # 中职没有镇区数据
rural_data.append(0) # 中职没有乡村数据
total_in_school.append(total_value / 10000) # 转换为万人
else:
urban_data.append(in_school_year_data.get("urban", 0) / 10000) # 转换为万人
town_data.append(in_school_year_data.get("town", 0) / 10000) # 转换为万人
rural_data.append(in_school_year_data.get("rural", 0) / 10000) # 转换为万人
# 计算总和作为总人数
calculated_total = in_school_year_data.get("urban", 0) + in_school_year_data.get("town", 0) + in_school_year_data.get("rural", 0)
total_in_school.append(calculated_total / 10000) # 转换为万人
else:
# 2025-2035年使用预测数据
if education_stage == 'preschool' and forecast_util:
if int(year) in enrollment_in_school:
total_value = enrollment_in_school[int(year)]
# 获取城区比例(使用最近一年的城区比例)
recent_year = str(int(year) - 1)
if recent_year in area_in_school["student_data"].get(education_stage, {}):
recent_data = area_in_school["student_data"].get(education_stage, {}).get(recent_year, {})
recent_urban = recent_data.get("urban", 0)
recent_total = recent_data.get("urban", 0) + recent_data.get("town", 0) + recent_data.get("rural", 0)
if recent_total > 0:
urban_ratio = recent_urban / recent_total
else:
urban_ratio = 0.5
else:
urban_ratio = 0.5
# 计算城乡分布
urban_value = int(total_value * urban_ratio)
remaining_value = total_value - urban_value
# 假设乡镇和农村按5:5分配剩余部分
town_value = int(remaining_value * 0.5)
rural_value = remaining_value - town_value
urban_data.append(urban_value / 10000)
town_data.append(town_value / 10000)
rural_data.append(rural_value / 10000)
total_in_school.append(total_value / 10000)
else:
# 没有预测数据,使用前一年数据
if len(total_in_school) > 0:
urban_data.append(urban_data[-1])
town_data.append(town_data[-1])
rural_data.append(rural_data[-1])
total_in_school.append(total_in_school[-1])
else:
urban_data.append(0)
town_data.append(0)
rural_data.append(0)
total_in_school.append(0)
else:
# 非学前教育或没有预测工具,使用前一年数据
if len(total_in_school) > 0:
urban_data.append(urban_data[-1])
town_data.append(town_data[-1])
rural_data.append(rural_data[-1])
total_in_school.append(total_in_school[-1])
else:
urban_data.append(0)
town_data.append(0)
rural_data.append(0)
total_in_school.append(0)
# 添加2022年基数的粉色折线
base_year = "2022"
# 找到2022年在years中的索引位置
base_index = years.index(base_year) if base_year in years else 0
# 获取2022年的总人数作为基数
base_value = total_in_school[base_index] if base_index < len(total_in_school) else 0
# 创建2022年基数折线数据2022-2035年
base_2022_line = []
for i, year in enumerate(years):
# 只在2022年及之后显示基数线
if i >= base_index:
base_2022_line.append(base_value)
else:
base_2022_line.append(None) # 2022年之前不显示
data = {
"xAxis_data": years,
"series_data_0": urban_data,
"series_data_1": town_data,
"series_data_2": rural_data,
"series_data_3": total_in_school,
"series_data_4": base_2022_line,
"education_stage": RuYuanZaiYuanModel.EDUCATION_STAGES.get(education_stage, '学前') # 添加教育阶段名称
}
return data