Files
report-admin/scripts/era2/07_deep_field_audit.py
T
lofyerandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 71db82393a Initial commit
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-07-13 15:38:41 +08:00

379 lines
19 KiB
Python

#!/usr/bin/env python3
"""
深度字段审计:逐方法 × 逐字段,精确检查赋分引擎每个赋分函数的数据覆盖。
"""
import sys
from pathlib import Path
from collections import defaultdict
import pandas as pd
import numpy as np
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "backend"))
from data_engine_era2 import DataEngineEra2
from config_era2 import SUBJECTS
def section(title):
print(f"\n{'=' * 80}")
print(f" {title}")
print(f"{'=' * 80}")
def check_exact_field(df, field_name, label=""):
"""检查精确字段名是否存在"""
hits = df[df["字段名称"] == field_name]
n_schools = hits["学校名称"].nunique() if len(hits) > 0 else 0
status = f"✅ {n_schools}校" if n_schools > 0 else "❌ 不存在"
return n_schools, status
def check_contains_field(df, keyword, label=""):
"""检查关键词匹配的字段"""
hits = df[df["字段名称"].str.contains(keyword, na=False)]
n_fields = hits["字段名称"].nunique() if len(hits) > 0 else 0
n_schools = hits["学校名称"].nunique() if len(hits) > 0 else 0
return n_fields, n_schools
def find_similar(all_fields, keyword, top=5):
"""模糊搜索"""
results = []
for f in all_fields:
if keyword in str(f):
results.append(f)
return results[:top]
def main():
engine = DataEngineEra2(district_filter=None)
engine.load_all()
course_df = engine._course_impl
subject_df = engine._subject_impl
all_course_fields = sorted(course_df["字段名称"].dropna().unique())
all_subject_fields = sorted(subject_df["字段名称"].dropna().unique())
all_fields = set(all_course_fields) | set(all_subject_fields)
total_schools = len(engine.schools)
print(f"总学校数: {total_schools}")
# ===== 按赋分方法逐个检查 =====
results = {} # method -> {field: (status, detail)}
def audit_method(method_name, dim_name, checks):
"""
checks: list of (source, type, field_or_keyword, description)
source: 'course' or 'subject'
type: 'exact' or 'contains'
"""
results[method_name] = {"dim": dim_name, "fields": []}
df_map = {"course": course_df, "subject": subject_df}
for source, check_type, field, desc in checks:
df = df_map[source]
if check_type == "exact":
n_schools, status = check_exact_field(df, field)
similar = []
if n_schools == 0:
similar = find_similar(all_course_fields if source == "course" else all_subject_fields, field[:4] if len(field) > 4 else field)
results[method_name]["fields"].append({
"field": field, "source": source, "type": check_type,
"desc": desc, "n_schools": n_schools, "status": status,
"similar": similar,
})
else: # contains
n_fields, n_schools = check_contains_field(df, field)
results[method_name]["fields"].append({
"field": field, "source": source, "type": check_type,
"desc": desc, "n_schools": n_schools, "n_fields": n_fields,
"status": f"✅ {n_fields}字段/{n_schools}校" if n_fields > 0 else "❌",
})
# ===== 1. 国家标准遵循 =====
audit_method("_score_national_standard", "国家标准遵循", [
("subject", "exact", "学科必修课周课时", "必修课周课时"),
("subject", "exact", "学科选择性必修课周课时", "选必课周课时"),
("subject", "exact", "学科类选修课周课时", "选修课周课时"),
])
# ===== 2. 课程结构建设 =====
audit_method("_score_course_structure", "课程结构建设", [
("course", "exact", "跨学科选修课门数", "跨学科选修课"),
("course", "exact", "综合主题选修课门数", "综合主题选修课"),
("course", "exact", "综合实践选修课门数", "综合实践选修课"),
("course", "exact", "三年应完成的研究性学习数量", "研究性学习数量"),
("course", "exact", "三年社会考察个数", "社会考察"),
("course", "exact", "三年志愿服务时长", "志愿服务"),
])
# ===== 3. 课程规范落实 =====
audit_method("_score_course_norms", "课程规范落实", [
("course", "contains", "建设规范文本", "规范文本"),
("course", "contains", "档案", "档案规范"),
("course", "contains", "已经建成并使用", "已建成使用"),
("course", "contains", "已经建成尚未使用", "已建成未使用"),
("course", "contains", "尚未建成", "尚未建成"),
])
# ===== 4. 教学方式变革 =====
audit_method("_score_teaching_reform", "教学方式变革", [
("subject", "contains", "认识程度", "认识程度"),
("subject", "contains", "落实程度", "落实程度"),
("subject", "contains", "体现形式", "实施方式体现形式"),
])
# ===== 5. 作业设计与管理变革 =====
audit_method("_score_homework_reform", "作业设计与管理变革", [
("subject", "exact", "实践类作业_有布置", "实践类作业"),
("subject", "exact", "表现类作业_有布置", "表现类作业"),
("subject", "exact", "跨学科作业_有布置", "跨学科作业"),
("subject", "exact", "团队合作类作业_有布置", "团队合作类作业"),
("subject", "contains", "作业属性标注", "作业属性标注"),
("subject", "exact", "回家作业时长控制_学校控制", "时长控制-学校"),
("subject", "exact", "回家作业时长控制_教研组负责", "时长控制-教研组"),
("subject", "exact", "作业批改范围_全部批改", "全部批改"),
("subject", "exact", "作业批改范围_部分练习", "部分批改"),
])
# ===== 6. 个性化辅导 =====
audit_method("_score_personalized_tutoring", "学科发展的个性化辅导", [
("subject", "exact", "个别辅导时长_每周>2h", "辅导>2h"),
("subject", "exact", "个别辅导时长_每周1~2h", "辅导1-2h"),
("subject", "exact", "个别辅导时长_每周<1h", "辅导<1h"),
("subject", "exact", "个别辅导时长_几乎无", "辅导-几乎无"),
("subject", "exact", "个别辅导实施方式_分散辅导", "分散辅导"),
("subject", "exact", "个别辅导实施方式_分组统一辅导", "分组辅导"),
("subject", "exact", "个别辅导实施方式_班级统一辅导", "班级辅导"),
])
# ===== 7. 生涯发展指导 =====
audit_method("_score_career_guidance", "学生生涯发展指导", [
("course", "exact", "生涯指导实施方式_专设课程", "专设课程"),
("course", "exact", "生涯指导实施方式_社会考察和志愿服务", "社考志愿"),
("course", "exact", "完成生涯指导的学生占比_90%+", "覆盖率90%+"),
("course", "exact", "生涯指导教师构成_本校和外聘结合", "师资-结合"),
("course", "exact", "生涯指导教师构成_本校为主", "师资-本校为主"),
("course", "exact", "生涯指导的校外资源支持程度", "校外资源"),
("course", "exact", "生涯指导的校内资源支持程度", "校内资源"),
])
# ===== 8. 培训支持 =====
audit_method("_score_training_support", "培训支持", [
("subject", "exact", "提供外校培训的教师人数", "外校培训人数"),
("subject", "exact", "区域培训指导人数", "区域培训人数"),
])
# ===== 9. 教研支持 =====
audit_method("_score_research_support", "教研支持", [
("subject", "exact", "学科教研组每学期活动次数", "教研活动次数"),
("subject", "exact", "学科教研组平均每次活动时长", "教研活动时长"),
("subject", "exact", "学科教研工作计划_有", "教研计划"),
("subject", "exact", "学科教研组校级展示_有", "校级展示"),
("subject", "exact", "学科教研组区域展示_有", "区域展示"),
("subject", "exact", "学科教研组成果发表_有", "成果发表"),
])
# ===== 10. 项目支持 =====
audit_method("_score_project_support", "项目支持", [
("subject", "exact", "学科承担的市级教改项目个数", "学科市级项目"),
("subject", "exact", "学科承担的区级教改项目个数", "学科区级项目"),
("subject", "exact", "学科承担的校级教改项目个数", "学科校级项目"),
("course", "exact", "学校负责的市级教改项目个数", "学校负责市级"),
("course", "exact", "学校参与的市级教改项目个数", "学校参与市级"),
("course", "exact", "学校负责的区级教改项目个数", "学校负责区级"),
("course", "exact", "学校参与的区级教改项目个数", "学校参与区级"),
("course", "exact", "校级教改项目个数", "校级项目"),
])
# ===== 11. 科学评价观 =====
audit_method("_score_scientific_evaluation", "科学评价观", [
("subject", "contains", "作业评价关注点", "作业评价"),
("subject", "contains", "课堂表现评价关注点", "课堂评价"),
("subject", "contains", "学科实践活动评价关注点", "实践评价"),
])
# ===== 12. 学业质量评估 =====
audit_method("_score_academic_evaluation", "学业质量评估", [
("subject", "exact", "作业评价工具_已经建成并使用", "作业工具-建成使用"),
("subject", "exact", "课堂表现评价工具_已经建成并使用", "课堂工具-建成使用"),
("subject", "exact", "作业评价工具_已经建成尚未使用", "作业工具-建成未用"),
("subject", "exact", "作业评价工具_尚未建成和使用", "作业工具-未建成"),
("subject", "exact", "学期考试分析_执行分析并存档", "考试分析-存档"),
("subject", "exact", "学期考试分析_执行分析,不要求存档", "考试分析-不存档"),
("subject", "exact", "学期考试分析_教师自己决定", "考试分析-自定"),
("subject", "exact", "表现性评价应用程度_经常", "表现性-经常"),
("subject", "exact", "表现性评价应用程度_有时", "表现性-有时"),
("subject", "exact", "表现性评价应用程度_总是", "表现性-总是"),
("subject", "exact", "表现性评价应用程度_从不", "表现性-从不"),
])
# ===== 13. 综合素质评估 =====
audit_method("_score_comprehensive_evaluation", "综合素质评估", [
("course", "exact", "综评评价体系_已经建成并使用", "综评-建成使用"),
("course", "exact", "综评评价体系_已经建成尚未使用", "综评-建成未用"),
("course", "exact", "综评评价体系_未建成", "综评-未建成"),
("course", "exact", "综评评价体系_不准备建设", "综评-不建设"),
("course", "exact", "综评信息化实现_自建平台支持", "综评IT-自建"),
("course", "exact", "综评信息化实现_借助第三方平台支持", "综评IT-三方"),
("course", "contains", "综评结果使用", "综评结果使用"),
("course", "contains", "综评应用", "综评应用"),
])
# ===== 14. 实践活动评估 =====
audit_method("_score_practice_evaluation", "实践活动评估", [
("course", "exact", "研究性学习评价工具_已经建成并使用", "研学评价-建成使用"),
("course", "exact", "研究性学习评价工具_尚未建成和使用", "研学评价-未建成"),
("course", "exact", "社会考察评价工具_已经建成并使用", "社考评价-建成使用"),
("course", "exact", "社会考察评价工具_尚未建成和使用", "社考评价-未建成"),
("subject", "exact", "学科实践活动工具_已经建成并使用", "学科实践-建成使用"),
("subject", "exact", "学科实践活动工具_已经建成尚未使用", "学科实践-建成未用"),
("subject", "exact", "学科实践活动工具_尚未建成和使用", "学科实践-未建成"),
])
# ===== 15. 区域推进 =====
audit_method("_score_regional_promotion", "区域推进", [
("course", "exact", "区域工作会参与_一月4次以上", "工作会-月4+"),
("course", "exact", "区域工作会参与_一月1次", "工作会-月1"),
("course", "exact", "区域工作会参与_二月1次", "工作会-两月1"),
("course", "exact", "区域工作会参与_三月1次", "工作会-季1"),
("course", "contains", "区域推进措施", "推进措施"),
])
# ===== 16. 环境支持 =====
audit_method("_score_environment_support", "环境支持", [
("course", "exact", "场馆供给_能满足需要", "场馆-满足"),
("course", "exact", "场馆供给_基本满足需要", "场馆-基本满足"),
("course", "exact", "场馆供给_难以满足需要", "场馆-难满足"),
("course", "exact", "专用教室供给_能满足需要", "专用教室-满足"),
("course", "exact", "专用教室供给_基本满足需要", "专用教室-基本满足"),
("course", "contains", "信息化平台功能", "信息化平台功能"),
])
# ===== 17. 资源支持 =====
audit_method("_score_resource_support", "资源支持", [
("subject", "exact", "必修课校内资源支持程度", "必修校内资源"),
("subject", "exact", "选择性必修课校内资源支持程度", "选必校内资源"),
("subject", "exact", "必修课校外资源支持程度", "必修校外资源"),
("subject", "exact", "选择性必修课校外资源支持程度", "选必校外资源"),
("subject", "exact", "学科教研组总人数", "教研组总人数"),
])
# ===== 18. 教学方式创新 =====
audit_method("_score_digital_teaching", "教学方式创新", [
("subject", "exact", "信息技术与教学融合的认识_所有人可做到", "IT融合-所有人"),
("subject", "exact", "信息技术与教学融合的认识_个别人可做到", "IT融合-个别人"),
("subject", "exact", "信息化终端使用比例_80%+", "终端-80%+"),
("subject", "exact", "信息化终端使用比例_60~79%", "终端-60~79%"),
("subject", "exact", "信息化终端使用比例_30~59%", "终端-30~59%"),
("subject", "exact", "信息化终端使用比例_30%-", "终端-30%-"),
])
# ===== 19. 评价精准化 =====
audit_method("_score_digital_evaluation", "评价精准化与个性化", [
("subject", "exact", "学业评价信息化实现_自建平台支持", "学评IT-自建"),
("subject", "exact", "学业评价信息化实现_借助第三方平台支持", "学评IT-三方"),
("subject", "exact", "学业评价信息化实现_没有平台支持", "学评IT-无"),
("course", "exact", "学校信息系统对选课支持程度", "选课系统"),
("course", "exact", "学校信息系统对排课支持程度", "排课系统"),
])
# ===== 20. 课程迭代优化 =====
audit_method("_score_digital_curriculum", "课程迭代优化", [
("course", "exact", "数据连通_有数据能互通", "数据互通"),
("course", "exact", "数据连通_有数据不互通", "数据不互通"),
("course", "exact", "管理业务的信息化应用_绝大部分", "管理IT-绝大部分"),
("course", "exact", "教学业务的信息化应用_绝大部分", "教学IT-绝大部分"),
("course", "exact", "已完成的网络课程门数", "网络课程数"),
])
# ===== 打印报告 =====
section("完整字段覆盖审计报告")
total_fields = 0
total_ok = 0
total_missing = 0
dim_summary = {}
for method, info in results.items():
dim = info["dim"]
ok = sum(1 for f in info["fields"] if f["n_schools"] > 0)
fail = sum(1 for f in info["fields"] if f["n_schools"] == 0)
total = len(info["fields"])
total_fields += total
total_ok += ok
total_missing += fail
pct = ok / total * 100 if total > 0 else 0
bar = "█" * int(pct / 5) + "░" * (20 - int(pct / 5))
print(f"\n{'─' * 80}")
print(f" {dim} ({method})")
print(f" [{bar}] {pct:.0f}% ({ok}/{total})")
print(f"{'─' * 80}")
for f in info["fields"]:
src_label = "课程表" if f["source"] == "course" else "学科表"
type_label = "精确" if f["type"] == "exact" else "关键词"
print(f" {f['status']:<16} [{src_label}/{type_label}] {f['field']}")
if f["n_schools"] == 0 and f.get("similar"):
print(f" → 近似: {f['similar'][:3]}")
dim_summary[dim] = {"ok": ok, "fail": fail, "total": total, "pct": pct}
# ===== 汇总 =====
section("维度覆盖率汇总")
print(f"\n{'维度':<20} {'覆盖':>5} {'缺失':>5} {'总数':>5} {'覆盖率':>8}")
print(f"{'─' * 50}")
for dim, s in dim_summary.items():
marker = "⚠️" if s["pct"] < 60 else "✅" if s["pct"] >= 80 else "⚡"
print(f"{dim:<20} {s['ok']:>5} {s['fail']:>5} {s['total']:>5} {s['pct']:>6.0f}% {marker}")
print(f"{'─' * 50}")
print(f"{'合计':<20} {total_ok:>5} {total_missing:>5} {total_fields:>5} {total_ok/total_fields*100:>6.0f}%")
# ===== ETL层面检查:一期有但二期没有的字段名模式 =====
section("ETL字段名差异分析")
# 检查常见差异模式
patterns_to_check = [
("个别辅导时长", "辅导时长字段命名"),
("信息技术与教学融合", "IT融合字段"),
("信息化终端使用比例", "终端使用比例"),
("信息化平台功能", "平台功能"),
("教学业务的信息化", "教学信息化"),
("数据连通", "数据连通"),
("已完成的网络课程", "网络课程"),
("作业批改范围", "作业批改"),
("实践类作业", "实践作业"),
("表现类作业", "表现作业"),
("跨学科作业", "跨学科作业"),
("团队合作类作业", "团队合作作业"),
]
for keyword, label in patterns_to_check:
course_hits = [f for f in all_course_fields if keyword in str(f)]
subject_hits = [f for f in all_subject_fields if keyword in str(f)]
if course_hits or subject_hits:
print(f"\n ✅ '{keyword}' ({label}):")
for h in course_hits:
print(f" 课程表: {h}")
for h in subject_hits:
print(f" 学科表: {h}")
else:
# 更宽松的搜索
kw_short = keyword[:4]
c2 = [f for f in all_course_fields if kw_short in str(f)]
s2 = [f for f in all_subject_fields if kw_short in str(f)]
print(f"\n ❌ '{keyword}' ({label}): 不存在")
if c2 or s2:
print(f" 近似(课程表): {c2[:5]}")
print(f" 近似(学科表): {s2[:5]}")
print(f"\n✅ 深度审计完成!")
if __name__ == "__main__":
main()