Initial commit
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
commit
71db82393a
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
测试脚本:完整Pipeline - 数据加载→赋分→PCA→标准化→水平判定→统计分析
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import json
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "backend"))
|
||||
|
||||
from app.engines.data_engine import DataEngine
|
||||
from app.engines.scoring_engine import ScoringEngine
|
||||
from app.engines.stats_engine import StatsEngine
|
||||
from app.config import DIMENSION_FRAMEWORK, LEVEL_THRESHOLDS
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 80)
|
||||
print("完整Pipeline测试:Excel → 赋分 → PCA → 标准化 → 水平判定")
|
||||
print("=" * 80)
|
||||
|
||||
# Step 1: 加载数据
|
||||
print("\n[Step 1] 加载Excel数据...")
|
||||
data_engine = DataEngine()
|
||||
data_engine.load_all()
|
||||
|
||||
# Step 2: 赋分
|
||||
print("\n[Step 2] 对所有学校进行赋分...")
|
||||
scoring_engine = ScoringEngine(data_engine)
|
||||
raw_scores = scoring_engine.score_all_schools()
|
||||
|
||||
# 打印赋分结果概要
|
||||
print("\n📊 赋分结果概要:")
|
||||
for school in data_engine.schools:
|
||||
scores = raw_scores[school]
|
||||
print(f"\n 🏫 {school}:")
|
||||
for dim, vals in scores.items():
|
||||
avg = sum(vals) / len(vals) if vals else 0
|
||||
print(f" {dim}: {len(vals)}个指标, 均值={avg:.2f}, 值={[round(v,1) for v in vals[:5]]}{'...' if len(vals) > 5 else ''}")
|
||||
|
||||
# Step 3: 统计分析
|
||||
print("\n[Step 3] PCA合成 + 标准化...")
|
||||
stats_engine = StatsEngine()
|
||||
sub_scores = stats_engine.compute_dimension_scores(raw_scores)
|
||||
print(f"\n三级维度标准化得分 (均值50, 标准差10):")
|
||||
print(sub_scores.round(2).to_string())
|
||||
|
||||
# Step 4: 二级维度聚合
|
||||
print("\n[Step 4] 二级维度聚合...")
|
||||
dim_scores = stats_engine.compute_dimension_aggregates(sub_scores)
|
||||
print(f"\n二级维度得分:")
|
||||
print(dim_scores.round(2).to_string())
|
||||
|
||||
# Step 5: 水平判定
|
||||
print("\n[Step 5] 水平判定...")
|
||||
levels = stats_engine.compute_levels(sub_scores)
|
||||
print(f"\n各学校各维度水平:")
|
||||
print(levels.to_string())
|
||||
|
||||
# Step 6: 聚类分析
|
||||
print("\n[Step 6] 聚类分析...")
|
||||
dim_cols = [c for c in dim_scores.columns if c in DIMENSION_FRAMEWORK]
|
||||
clusters = stats_engine.cluster_analysis(dim_scores[dim_cols])
|
||||
print(f"\n学校聚类结果:")
|
||||
for school, cluster in clusters["school_clusters"].items():
|
||||
print(f" {school}: {cluster}")
|
||||
|
||||
# Step 7: 相关性
|
||||
print("\n[Step 7] 维度间相关性:")
|
||||
corr = stats_engine.correlation_analysis(dim_scores)
|
||||
print(corr.round(3).to_string())
|
||||
|
||||
# Step 8: 生成一所学校的完整报告数据
|
||||
test_school = "延安中学"
|
||||
print(f"\n[Step 8] 生成 {test_school} 的完整报告数据包...")
|
||||
report_data = stats_engine.compute_school_report_data(test_school, sub_scores, dim_scores)
|
||||
|
||||
print(f"\n📋 {test_school} 报告数据概要:")
|
||||
print(f" 总体得分: {report_data['overall']['score']}")
|
||||
print(f" 区内排名: {report_data['overall']['rank_in_district']}/{report_data['overall']['total_schools']}")
|
||||
print(f" 聚类类型: {report_data['overall']['cluster']}")
|
||||
|
||||
print(f"\n 二级维度得分:")
|
||||
for dim, data in report_data['dimensions'].items():
|
||||
print(f" {dim}: {data['score']} (区均值{data['district_avg']}, 差异{data['diff_district']:+.2f})")
|
||||
|
||||
print(f"\n 三级维度水平:")
|
||||
for sub_dim, data in report_data['sub_dimensions'].items():
|
||||
print(f" {sub_dim}: 得分{data['score']}, 水平{data['level']}, {data['level_description'][:30]}")
|
||||
|
||||
# 保存报告数据为JSON
|
||||
output_dir = Path(__file__).parent.parent / "output"
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
# 清理numpy类型以便JSON序列化
|
||||
def clean_for_json(obj):
|
||||
import numpy as np
|
||||
if isinstance(obj, dict):
|
||||
return {k: clean_for_json(v) for k, v in obj.items()}
|
||||
elif isinstance(obj, list):
|
||||
return [clean_for_json(v) for v in obj]
|
||||
elif isinstance(obj, (np.integer,)):
|
||||
return int(obj)
|
||||
elif isinstance(obj, (np.floating,)):
|
||||
return round(float(obj), 4)
|
||||
elif isinstance(obj, np.ndarray):
|
||||
return obj.tolist()
|
||||
elif isinstance(obj, float):
|
||||
return round(obj, 4)
|
||||
return obj
|
||||
|
||||
report_clean = clean_for_json(report_data)
|
||||
with open(output_dir / f"{test_school}_report_data.json", "w", encoding="utf-8") as f:
|
||||
json.dump(report_clean, f, ensure_ascii=False, indent=2)
|
||||
print(f"\n✅ 报告数据已保存到 output/{test_school}_report_data.json")
|
||||
|
||||
# 保存所有学校的得分汇总
|
||||
all_scores = {
|
||||
"sub_dimension_scores": clean_for_json(sub_scores.to_dict()),
|
||||
"dimension_scores": clean_for_json(dim_scores.to_dict()),
|
||||
"levels": clean_for_json(levels.to_dict()),
|
||||
"clusters": clean_for_json(clusters),
|
||||
}
|
||||
with open(output_dir / "all_schools_scores.json", "w", encoding="utf-8") as f:
|
||||
json.dump(all_scores, f, ensure_ascii=False, indent=2)
|
||||
print(f"✅ 全校得分汇总已保存到 output/all_schools_scores.json")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("✅ 完整Pipeline测试完成!")
|
||||
print("=" * 80)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user