Files
YunNanProject/Model/RuYuanZaiYuanCountModel.py
2025-09-11 14:35:28 +08:00

259 lines
10 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
from pyecharts import options as opts
from pyecharts.charts import Bar, Line
from pyecharts.globals import CurrentConfig
from Config.Config import ONLINE_HOST
CurrentConfig.ONLINE_HOST = ONLINE_HOST
class RuYuanZaiYuanModel:
@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():
# 获取学前教育相关数据
# enrollment_data, in_school_data = RuYuanZaiYuanModel.load_student_data()
#
# # 提取云南省级数据
# yunnan_enroll = next((item for item in enrollment_data if item["area_name"] == "云南省"), None)
#
# if not yunnan_enroll:
# return {}
#
# # 提取年份数据(2015-2024)
# years = [str(year) for year in range(2015, 2025)]
#
# # 构建学前教育数据
# urban_data = [] # 城区数据
# town_data = [] # 镇区数据
# rural_data = [] # 乡村数据
# total_enroll = [] # 总入园数
#
# for year in years:
# enroll_data = yunnan_enroll["education_data"]["preschool"].get(year, {})
# 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) # 转换为万人
# # 计算总和作为总入园数而非使用文件中的total字段
# calculated_total = enroll_data.get("urban", 0) + enroll_data.get("town", 0) + enroll_data.get("rural", 0)
# total_enroll.append(calculated_total / 10000) # 转换为万人
xAxis = ["2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026"]
series_data_1 = [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6]
series_data_2 = [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6]
series_data_3 = [2.4, 5.2, 8.0, 25.4, 27.7, 73.7, 155.6]
series_data_4 = [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3]
line_data = [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3]
data = {"xAxis_data": xAxis,
"series_data_1": series_data_1,
"series_data_2": series_data_2,
"series_data_3": series_data_3,
"series_data_4": series_data_4,
"line_data": line_data
}
return data
@staticmethod
def generate_in_school_education_config():
# 获取学前教育相关数据
enrollment_data, in_school_data = RuYuanZaiYuanModel.load_student_data()
# 提取云南省级数据
yunnan_in_school = next((item for item in in_school_data if item["area_name"] == "云南省"), None)
if not yunnan_in_school:
return {}
# 提取年份数据(2015-2024)
years = [str(year) for year in range(2015, 2025)]
# 构建学前教育数据
urban_data = [] # 城区数据
town_data = [] # 镇区数据
rural_data = [] # 乡村数据
total_in_school = [] # 总在园数
for year in years:
# 将education_data改为student_data
in_school_year_data = yunnan_in_school["student_data"]["preschool"].get(year, {})
# 先获取原始数据
urban_val = in_school_year_data.get("urban", 0)
town_val = in_school_year_data.get("town", 0)
rural_val = in_school_year_data.get("rural", 0)
# 转换为万人并添加到各自列表
urban_data.append(urban_val / 10000) # 转换为万人
town_data.append(town_val / 10000) # 转换为万人
rural_data.append(rural_val / 10000) # 转换为万人
# 计算总和并转换为万人
calculated_total = (urban_val + town_val + rural_val) / 10000 # 先计算总和再转换为万人
total_in_school.append(calculated_total)
# 添加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-2024年
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年之前不显示
# 构建ECharts配置
option = {
"tooltip": {
"trigger": "axis",
"axisPointer": {
"type": "cross",
"crossStyle": {"color": "#999"}
},
"textStyle": {"color": "#333"},
"backgroundColor": "rgba(255, 255, 255, 0.8)",
"borderColor": "rgba(0, 0, 0, 0.2)",
"borderWidth": 1
},
"legend": {
"data": ["城区", "镇区", "乡村", "总在园数", "2022年基数(万人)"],
"top": 30,
"textStyle": {"color": "#333"},
"icon": "roundRect",
"itemWidth": 12,
"itemHeight": 12
},
"xAxis": [
{
"type": "category",
"data": years,
"axisPointer": {"type": "shadow"},
"axisLabel": {"color": "#333"},
"axisLine": {"lineStyle": {"color": "#333"}}
}
],
"yAxis": [
{
"type": "value",
"name": "人数",
"min": 0,
"max": 200, # 将左侧Y轴最大值从100修改为200万
"interval": 40, # 调整间隔为40万确保坐标轴上有5个主要刻度(0,40,80,120,160,200)
"axisLabel": {
"formatter": "{value} 万人",
"color": "#333"
},
"axisLine": {"lineStyle": {"color": "#333"}},
"splitLine": {"lineStyle": {"color": "rgba(0,0,0,0.1)"}}
},
{
"type": "value",
"name": "总在园数",
"min": 0,
"max": 320, # 将右侧Y轴最大值从160扩大一倍到320万
"interval": 60, # 调整间隔为60万
"position": "right",
"nameLocation": "end",
"nameGap": 30,
"axisLabel": {
"formatter": "{value} 万人",
"color": "#00a859" # 改为绿色
},
"axisLine": {"show": True, "lineStyle": {"color": "#00a859"}}, # 改为绿色
"axisTick": {"show": True},
"splitLine": {"show": False}
}
],
"series": [
{
"name": "城区",
"type": "bar",
"data": urban_data,
"itemStyle": {
"color": "#5470c6",
"borderRadius": [6, 6, 0, 0]
},
"barWidth": "25%",
"barGap": "-10%"
},
{
"name": "镇区",
"type": "bar",
"data": town_data,
"itemStyle": {
"color": "#91cc75",
"borderRadius": [6, 6, 0, 0]
},
"barWidth": "25%",
"barGap": "-10%"
},
{
"name": "乡村",
"type": "bar",
"data": rural_data,
"itemStyle": {
"color": "#fac858",
"borderRadius": [6, 6, 0, 0]
},
"barWidth": "25%",
"barGap": "-10%"
},
{
"name": "总在园数",
"type": "line",
"yAxisIndex": 1,
"data": total_in_school,
"lineStyle": {"color": "#00a859", "width": 3}, # 改为绿色
"symbol": "circle",
"symbolSize": 8,
"itemStyle": {"color": "#00a859"}, # 改为绿色
"emphasis": {
"focus": "series"
},
"z": 10 # 确保折线图显示在最上层
},
# 添加2022年基数的粉色折线
{
"name": "2022年基数(万人)",
"type": "line",
"yAxisIndex": 1,
"data": base_2022_line,
"lineStyle": {"color": "#ff9e9e", "width": 2, "type": "solid"},
"symbol": "circle",
"symbolSize": 6,
"itemStyle": {"color": "#ff9e9e"},
"emphasis": {
"focus": "series"
},
"z": 5 # 确保折线图显示在柱状图之上,但在总在园数折线之下
}
],
"grid": {
"left": "3%",
"right": "15%", # 稍微增加右侧边距确保Y轴标签不被截断
"bottom": "3%",
"containLabel": True
}
}
return option