大模型写系统模板

# -*- coding: utf-8 -*-
import os

# 定义项目根目录名称
PROJECT_ROOT = "flight_analysis_system"

# 1. 创建项目目录结构(沿用NBA模板目录结构,修正缩进统一问题)
dirs = [
    PROJECT_ROOT,
    os.path.join(PROJECT_ROOT, "static"),
    os.path.join(PROJECT_ROOT, "static", "css"),
    os.path.join(PROJECT_ROOT, "static", "images"),
    os.path.join(PROJECT_ROOT, "templates")
]
for dir_path in dirs:
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)
        print(f"创建目录:{dir_path}")

# 2. 定义所有文件完整内容(修正所有格式错误,确保可运行)
file_contents = {
    # -------------------- requirements.txt(航班项目依赖,版本兼容无冲突) --------------------
    os.path.join(PROJECT_ROOT, "requirements.txt"): """flask==2.3.3
pandas==2.1.4
numpy==1.26.2
matplotlib==3.8.2
openpyxl==3.1.2
Werkzeug==2.3.7""",

    # -------------------- static/css/style.css(完全复用模板样式,CSS语法无错误) --------------------
    os.path.join(PROJECT_ROOT, "static", "css", "style.css"): """/* 全局样式重置 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "Microsoft YaHei", "SimHei", sans-serif;
}

/* 全局背景渐变(色彩艳丽) */
body {
    background: linear-gradient(135deg, #FF6B6B, #4ECDC4, #45B7D1, #FFD166);
    background-attachment: fixed;
    min-height: 100vh;
}

/* 导航栏样式 */
.nav-bar {
    background: rgba(0, 0, 0, 0.8);
    padding: 1.2rem 0;
    position: sticky;
    top: 0;
    z-index: 999;
    box-shadow: 0 4px 12px rgba(0,0,0,0.5);
}

.nav-container {
    width: 90%;
    margin: 0 auto;
    display: flex;
    justify-content: space-around;
}

.nav-item {
    color: #fff;
    text-decoration: none;
    font-size: 1.1rem;
    font-weight: bold;
    padding: 0.5rem 1rem;
    border-radius: 8px;
    transition: all 0.3s ease;
    background: rgba(255,255,255,0.1);
}

.nav-item:hover {
    background: #FF6B6B;
    transform: translateY(-3px);
    box-shadow: 0 4px 8px rgba(255,107,107,0.5);
}

/* 页面容器样式 */
.container {
    width: 90%;
    margin: 2rem auto;
    background: rgba(255,255,255,0.95);
    border-radius: 16px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.3);
    padding: 2rem;
}

/* 标题样式 */
.page-title {
    text-align: center;
    color: #FF3838;
    font-size: 2.5rem;
    font-weight: bold;
    margin-bottom: 2rem;
    text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}

.sub-title {
    color: #2E86AB;
    font-size: 1.8rem;
    margin: 1.5rem 0 1rem;
    border-left: 5px solid #FF6B6B;
    padding-left: 1rem;
}

/* 图表卡片布局(多元素排列) */
.chart-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
    gap: 2rem;
    margin-top: 2rem;
}

.chart-card {
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.1);
    padding: 1.5rem;
    transition: all 0.3s ease;
}

.chart-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 24px rgba(79,209,197,0.4);
}

.chart-title {
    text-align: center;
    color: #45B7D1;
    font-size: 1.3rem;
    margin-bottom: 1rem;
    font-weight: bold;
}

/* 图表图片样式 */
.chart-img {
    width: 100%;
    height: auto;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* 首页入口按钮样式 */
.index-buttons {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1.5rem;
    margin-top: 3rem;
}

.index-btn {
    background: linear-gradient(45deg, #FF6B6B, #FF8E53);
    color: #fff;
    text-align: center;
    padding: 2rem 1rem;
    border-radius: 12px;
    text-decoration: none;
    font-size: 1.2rem;
    font-weight: bold;
    box-shadow: 0 4px 12px rgba(255,107,107,0.3);
    transition: all 0.3s ease;
}

.index-btn:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(255,107,107,0.5);
    background: linear-gradient(45deg, #FF8E53, #FF6B6B);
    color: #fff;
    text-decoration: none;
}

/* 文本样式 */
.desc-text {
    font-size: 1.1rem;
    color: #333;
    line-height: 1.8;
    margin: 1rem 0;
    text-align: center;
}

.about-text {
    font-size: 1.1rem;
    color: #555;
    line-height: 2;
    margin: 1.5rem 0;
}

/* 页脚样式 */
.footer {
    text-align: center;
    padding: 1.5rem 0;
    color: #fff;
    background: rgba(0,0,0,0.8);
    margin-top: 3rem;
    border-radius: 0 0 16px 16px;
}""",

    # -------------------- flight_data_analysis.py(修正所有格式错误:缩进/文档字符串/容错性) --------------------
    os.path.join(PROJECT_ROOT, "flight_data_analysis.py"): """# -*- coding: utf-8 -*-
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager

# 航班数据处理与可视化脚本
# 自动生成11张多彩图表,保存至static/images目录

# --------------------------
# 1. 图表保存目录(适配模板结构,无路径错误)
# --------------------------
IMAGE_DIR = "static/images"
if not os.path.exists(IMAGE_DIR):
    os.makedirs(IMAGE_DIR)

# --------------------------
# 2. 设置Matplotlib中文支持(解决乱码,修正函数格式)
# --------------------------
def find_chinese_font():
    candidates = ["SimHei", "Microsoft YaHei", "MSYH", "Noto Sans CJK", "WenQuanYi", "Arial Unicode MS"]
    sys_fonts = font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
    name_to_path = {}
    for f in sys_fonts:
        try:
            prop = font_manager.FontProperties(fname=f)
            name = prop.get_name()
            name_to_path[name] = f
        except Exception:
            continue
    for c in candidates:
        for name, path in name_to_path.items():
            if c.lower() in name.lower() or c.lower() in path.lower():
                return path, name
    return None, None

font_path, font_name = find_chinese_font()
if font_path:
    plt.rcParams['font.sans-serif'] = [font_name]
else:
    plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 负号正常显示
plt.rcParams['figure.figsize'] = (10, 6)  # 默认图表大小

# --------------------------
# 3. 数据转换辅助函数(修正函数缩进和返回值格式)
# --------------------------
def to_minutes(s):
    if pd.isna(s):
        return np.nan
    s = str(s)
    if "小时" in s:
        parts = s.split("小时")
        h = 0
        try:
            h = int(parts[0])
        except:
            h = 0
        m = 0
        if len(parts) > 1 and "分钟" in parts[1]:
            mp = parts[1].replace("分钟", "").strip()
            try:
                m = int(mp)
            except:
                m = 0
        return h * 60 + m
    if "分钟" in s:
        ns = s.replace("分钟", "").strip()
        try:
            return int(ns)
        except:
            return np.nan
    try:
        return float(s)
    except:
        return np.nan

def parse_hour(t):
    try:
        return int(str(t).split(":")[0])
    except:
        return np.nan

# --------------------------
# 4. 航班数据可视化核心函数(修正索引错误和缩进问题)
# --------------------------
def flight_data_analysis():
    # 优先读取用户指定Excel文件,无则生成示例数据
    excel_file = "光用24年一年的就行-22年1月1日至24年12月31日航班数据.xlsx"
    if os.path.exists(excel_file):
        print(f"检测到 {excel_file},正在读取...")
        df = pd.read_excel(excel_file, nrows=300)
    else:
        print("未检测到指定Excel文件,生成示例航班数据...")
        np.random.seed(42)
        cities = ["北京", "上海", "广州", "深圳", "成都", "重庆", "杭州", "西安"]
        airlines = ["中国国际航空", "中国南方航空", "中国东方航空", "海南航空", "深圳航空", "厦门航空"]
        aircrafts = ["B737", "A320", "B787", "A330", "A350", "B777"]
        dates = pd.date_range(start="2024-01-01", end="2024-01-10")

        sample_data = {
            "出发城市": np.random.choice(cities, 300),
            "到达城市": np.random.choice(cities, 300),
            "起飞机场": np.random.choice(["北京首都机场", "上海浦东机场", "广州白云机场", "深圳宝安机场", "成都双流机场"], 300),
            "到达机场": np.random.choice(["北京首都机场", "上海浦东机场", "广州白云机场", "深圳宝安机场", "成都双流机场"], 300),
            "起飞机场x": np.random.uniform(100, 120, 300),
            "起飞机场y": np.random.uniform(30, 40, 300),
            "航空公司": np.random.choice(airlines, 300),
            "机型": np.random.choice(aircrafts, 300),
            "里程(公里)": np.random.randint(500, 3000, 300),
            "价格(元)": np.random.randint(300, 2000, 300),
            "人数": np.random.randint(50, 200, 300),
            "航班班次": np.random.randint(1, 5, 300),
            "准点率": np.random.uniform(0.8, 0.99, 300),
            "平均误点时间": np.random.choice(["10分钟", "20分钟", "1小时5分钟", "30分钟", "5分钟"], 300),
            "起飞时间": np.random.choice(["08:30", "10:15", "13:45", "16:20", "19:00", "21:30"], 300),
            "降落时间": np.random.choice(["10:30", "12:15", "15:45", "18:20", "21:00", "23:30"], 300),
            "日期": np.random.choice(dates, 300),
            "周一班期": np.random.choice(["有班期", ""], 300),
            "周二班期": np.random.choice(["有班期", ""], 300),
            "周三班期": np.random.choice(["有班期", ""], 300),
            "周四班期": np.random.choice(["有班期", ""], 300),
            "周五班期": np.random.choice(["有班期", ""], 300),
            "周六班期": np.random.choice(["有班期", ""], 300),
            "周日班期": np.random.choice(["有班期", ""], 300)
        }
        df = pd.DataFrame(sample_data)

    # 数据清洗(修正列名索引错误,增加容错判断)
    df.columns = [c.strip() for c in df.columns]
    # 数值列转换
    numeric_cols = ["里程(公里)", "价格(元)", "人数"]
    for c in numeric_cols:
        if c in df.columns:
            df[c] = pd.to_numeric(df[c], errors="coerce")
    # 准点率转百分比
    if "准点率" in df.columns:
        df["准点率"] = pd.to_numeric(df["准点率"], errors="coerce") * 100
    # 误点时间转分钟
    if "平均误点时间" in df.columns:
        df["平均误点_minutes"] = df["平均误点时间"].apply(to_minutes)
    # 起飞/降落小时提取
    if "起飞时间" in df.columns:
        df["起飞小时"] = df["起飞时间"].apply(parse_hour)
    if "降落时间" in df.columns:
        df["降落小时"] = df["降落时间"].apply(parse_hour)
    # 日期转换
    if "日期" in df.columns:
        df["日期"] = pd.to_datetime(df["日期"], errors="coerce")
    # 班期标志
    weekday_cols = []
    for w in ["周一班期","周二班期","周三班期","周四班期","周五班期","周六班期","周日班期"]:
        if w in df.columns:
            df[w + "_flag"] = df[w].fillna("").apply(lambda s: 1 if "有班期" in str(s) else 0)
            weekday_cols.append(w + "_flag")
    # 航线字段
    if "出发城市" in df.columns and "到达城市" in df.columns:
        df["route"] = df["出发城市"].astype(str) + " → " + df["到达城市"].astype(str)
    else:
        df["route"] = "未知航线"
    # 机场流量聚合(增加非空判断)
    if "起飞机场" in df.columns and "人数" in df.columns and "航班班次" in df.columns:
        airport_traffic = df.groupby("起飞机场").agg({
            "人数": "sum",
            "航班班次": "count",
            "起飞机场x": "first",
            "起飞机场y": "first"
        }).rename(columns={"航班班次":"航班数"}).reset_index()
    else:
        # 构造默认机场流量数据,避免报错
        airport_traffic = pd.DataFrame({
            "起飞机场": ["北京首都机场", "上海浦东机场"],
            "人数": [1000, 800],
            "航班数": [50, 40],
            "起飞机场x": [116.4, 121.5],
            "起飞机场y": [39.9, 31.2]
        })

    # 颜色配置(多彩可视化,修正颜色列表索引问题)
    cmap = plt.get_cmap("tab20")
    def color_list(n):
        return [cmap(i % 20) for i in range(n)]

    # --------------------------
    # 生成11张航班可视化图表(增加数据非空判断,避免绘图报错)
    # --------------------------
    # 图表1:起飞机场分布(点大小=人数)
    fig = plt.figure(figsize=(10,7))
    if not airport_traffic.empty:
        # 限制点大小范围,避免异常值
        s_values = np.clip(airport_traffic["人数"].fillna(0)/2, 20, 900)
        plt.scatter(airport_traffic["起飞机场x"], airport_traffic["起飞机场y"],
                    s=s_values, alpha=0.85, c=color_list(len(airport_traffic)))
        # 避免循环索引错误
        for i, r in airport_traffic.iterrows():
            plt.text(r["起飞机场x"], r["起飞机场y"], r["起飞机场"], fontsize=9)
    plt.xlabel("经度")
    plt.ylabel("纬度")
    plt.title("起飞机场分布(点大小表示累计人数)")
    plt.tight_layout()
    plt.savefig(os.path.join(IMAGE_DIR, "airport_distribution.png"), dpi=300)
    plt.close()

    # 图表2:前10航线航班数
    if "route" in df.columns:
        top_routes = df["route"].value_counts().head(10)
        fig = plt.figure(figsize=(10,6))
        # 修正倒序显示的索引问题
        bars = plt.barh(top_routes.index[::-1], top_routes.values[::-1], color=color_list(len(top_routes)))
        plt.title("前10条航线航班数")
        plt.xlabel("航班记录数")
        plt.tight_layout()
        plt.savefig(os.path.join(IMAGE_DIR, "top10_routes_count.png"), dpi=300)
        plt.close()

    # 图表3:航空公司平均准点率
    if "准点率" in df.columns and "航空公司" in df.columns:
        airlines_data = df.groupby("航空公司")["准点率"].mean().sort_values(ascending=False)
        if not airlines_data.empty:
            fig = plt.figure(figsize=(10,6))
            plt.bar(airlines_data.index, airlines_data.values, color=color_list(len(airlines_data)))
            plt.xticks(rotation=45, ha="right")
            plt.ylabel("平均准点率 (%)")
            plt.title("各航空公司平均准点率")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "airline_ontime.png"), dpi=300)
            plt.close()

    # 图表4:票价分布直方图
    if "价格(元)" in df.columns:
        prices = df["价格(元)"].dropna()
        if not prices.empty:
            fig = plt.figure(figsize=(8,6))
            plt.hist(prices, bins=12, alpha=0.9, color=cmap(2))
            plt.xlabel("票价(元)")
            plt.title("票价分布")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "price_distribution.png"), dpi=300)
            plt.close()

    # 图表5:航空公司票价箱线图
    if "航空公司" in df.columns and "价格(元)" in df.columns:
        # 过滤空值分组
        group_data = []
        group_labels = []
        for name, g in df.groupby("航空公司"):
            g_prices = g["价格(元)"].dropna()
            if not g_prices.empty:
                group_data.append(g_prices.values)
                group_labels.append(name)
        if len(group_data) > 0:
            fig = plt.figure(figsize=(10,6))
            bplot = plt.boxplot(group_data, labels=group_labels, patch_artist=True)
            # 修正颜色赋值索引问题
            for idx, (patch, color) in enumerate(zip(bplot['boxes'], color_list(len(group_labels)))):
                patch.set_facecolor(color)
            plt.xticks(rotation=45, ha="right")
            plt.ylabel("票价(元)")
            plt.title("航空公司间票价分布(箱线图)")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "airline_price_box.png"), dpi=300)
            plt.close()

    # 图表6:票价vs里程散点+回归线
    if "里程(公里)" in df.columns and "价格(元)" in df.columns:
        mask = df["里程(公里)"].notna() & df["价格(元)"].notna()
        x = df.loc[mask, "里程(公里)"]
        y = df.loc[mask, "价格(元)"]
        if not x.empty and not y.empty:
            fig = plt.figure(figsize=(8,6))
            plt.scatter(x, y, alpha=0.8, c=color_list(len(x)))
            # 修正回归线拟合的索引错误
            if len(x) > 1:
                coef = np.polyfit(x, y, 1)
                xp = np.linspace(x.min(), x.max(), 200)
                plt.plot(xp, np.polyval(coef, xp), linestyle="--", linewidth=2, color='black')
                plt.annotate(f"y={coef[0]:.2f}x+{coef[1]:.1f}", xy=(0.05,0.95), xycoords="axes fraction", va="top")
            plt.xlabel("里程(公里)")
            plt.ylabel("票价(元)")
            plt.title("票价与里程关系")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "price_vs_mileage.png"), dpi=300)
            plt.close()

    # 图表7:准点率vs里程散点
    if "准点率" in df.columns and "里程(公里)" in df.columns:
        mask2 = df["准点率"].notna() & df["里程(公里)"].notna()
        x2 = df.loc[mask2, "里程(公里)"]
        y2 = df.loc[mask2, "准点率"]
        if not x2.empty and not y2.empty:
            fig = plt.figure(figsize=(8,6))
            plt.scatter(x2, y2, alpha=0.8, c=color_list(len(x2)))
            plt.xlabel("里程(公里)")
            plt.ylabel("准点率 (%)")
            plt.title("准点率与里程关系")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "ontime_vs_mileage.png"), dpi=300)
            plt.close()

    # 图表8:每周班期航班数
    weekday_flags = [c for c in df.columns if c.endswith("_flag")]
    if len(weekday_flags) > 0:
        counts = df[weekday_flags].sum().values
        days = ["周一","周二","周三","周四","周五","周六","周日"]
        # 确保长度一致
        if len(counts) == len(days):
            fig = plt.figure(figsize=(9,4))
            plt.bar(days, counts, color=color_list(7))
            plt.ylabel("有班期航班数")
            plt.title("每周各天有班期的航班数量")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "weekday_schedule.png"), dpi=300)
            plt.close()

    # 图表9:起飞小时分布
    if "起飞小时" in df.columns:
        hours = df["起飞小时"].dropna().astype(int)
        if not hours.empty:
            fig = plt.figure(figsize=(10,4))
            plt.hist(hours, bins=range(0,25), align='left', rwidth=0.8, color=cmap(1))
            plt.xlabel("起飞小时(24h)")
            plt.title("起飞小时分布")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "departure_hour.png"), dpi=300)
            plt.close()

    # 图表10:前10航线乘客数
    if "route" in df.columns and "人数" in df.columns:
        route_pass = df.groupby("route")["人数"].sum().sort_values(ascending=False).head(10)
        if not route_pass.empty:
            fig = plt.figure(figsize=(10,6))
            plt.barh(route_pass.index[::-1], route_pass.values[::-1], color=color_list(len(route_pass)))
            plt.xlabel("乘客总数")
            plt.title("乘客人数最多的前10条航线")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "top10_routes_passengers.png"), dpi=300)
            plt.close()

    # 图表11:机型占比饼图
    if "机型" in df.columns:
        counts = df["机型"].value_counts().head(8)
        if not counts.empty:
            fig = plt.figure(figsize=(7,7))
            plt.pie(counts.values, labels=counts.index, autopct="%1.1f%%", startangle=140, colors=color_list(len(counts)))
            plt.title("主要机型占比(前8)")
            plt.axis("equal")
            plt.tight_layout()
            plt.savefig(os.path.join(IMAGE_DIR, "aircraft_type_pie.png"), dpi=300)
            plt.close()

    # 输出分析摘要(增加非空判断,避免报错)
    print("=== 航班数据可视化分析摘要 ===")
    print(f"分析航班记录数: {len(df)}")
    print(f"涉及航线数: {df['route'].nunique() if 'route' in df.columns else 0}")
    print(f"涉及航空公司数: {df['航空公司'].nunique() if '航空公司' in df.columns else 0}")
    print(f"涉及机场数: {df['起飞机场'].nunique() if '起飞机场' in df.columns else 0}")
    print(f"所有图表已保存至 {IMAGE_DIR} 目录")

if __name__ == "__main__":
    flight_data_analysis()""",

    # -------------------- app.py(修正导入和函数调用格式,无语法错误) --------------------
    os.path.join(PROJECT_ROOT, "app.py"): """# -*- coding: utf-8 -*-
from flask import Flask, render_template
import os
import flight_data_analysis

# 初始化Flask应用
app = Flask(__name__)

# 启动时自动生成航班可视化图表(增加文件存在判断的容错性)
chart_check_path = os.path.join("static", "images", "airport_distribution.png")
if not os.path.exists(chart_check_path):
    print("正在生成航班可视化图表...")
    flight_data_analysis.flight_data_analysis()
    print("图表生成完成!")

# --------------------------
# 路由配置(多页面跳转,沿用模板导航结构,无语法错误)
# --------------------------
# 首页
@app.route('/')
def index():
    return render_template('index.html')

# 机场分析页面
@app.route('/airport')
def airport_analysis():
    return render_template('airport_analysis.html')

# 航线分析页面
@app.route('/route')
def route_analysis():
    return render_template('route_analysis.html')

# 航空公司分析页面
@app.route('/airline')
def airline_analysis():
    return render_template('airline_analysis.html')

# 票价分析页面
@app.route('/price')
def price_analysis():
    return render_template('price_analysis.html')

# 时间分析页面
@app.route('/time')
def time_analysis():
    return render_template('time_analysis.html')

# 关于系统页面
@app.route('/about')
def about():
    return render_template('about.html')

# 程序入口
if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=5000)""",

    # -------------------- templates/index.html(修正HTML标签格式,无闭合错误) --------------------
    os.path.join(PROJECT_ROOT, "templates", "index.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>航班数据可视化系统 - 首页</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 全国航班数据可视化分析系统</h1>

        <h2 class="sub-title">一、系统快速入口</h2>
        <div class="index-buttons">
            <a href="/airport" class="index-btn">机场分析<br>(地理分布/客流规模)</a>
            <a href="/route" class="index-btn">航线分析<br>(热门航线/乘客排名)</a>
            <a href="/airline" class="index-btn">航空公司<br>(准点率/票价分布)</a>
            <a href="/price" class="index-btn">票价分析<br>(价格分布/里程关联)</a>
            <a href="/time" class="index-btn">时间分析<br>(班期/起飞时段)</a>
            <a href="/about" class="index-btn">关于系统<br>(技术栈&说明)</a>
        </div>

        <h2 class="sub-title">二、系统核心亮点</h2>
        <p class="about-text">
            1.  多页面布局:7个功能页面,导航清晰,操作便捷<br>
            2.  高清可视化:11张不同类型图表,覆盖机场/航线/票价等全维度<br>
            3.  美观适配:色彩艳丽渐变背景,卡片悬浮特效,支持多设备响应式显示<br>
            4.  自动生成:启动即生成图表,无需手动处理数据,中文无乱码<br>
            5.  技术支撑:Python+Flask构建,兼顾效率与易用性
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/airport_analysis.html(修正HTML样式格式) --------------------
    os.path.join(PROJECT_ROOT, "templates", "airport_analysis.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>机场分析 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 机场分布深度分析</h1>

        <h2 class="sub-title">一、核心可视化图表</h2>
        <div class="chart-grid" style="justify-content: center;">
            <!-- 机场分布图表 -->
            <div class="chart-card" style="grid-column: span 2; max-width: 1200px;">
                <h3 class="chart-title">起飞机场地理分布(点大小=累计乘客数)</h3>
                <img src="{{ url_for('static', filename='images/airport_distribution.png') }}" alt="机场分布" class="chart-img">
            </div>
        </div>

        <h2 class="sub-title">二、分析说明</h2>
        <p class="about-text">
            1.  数据维度:展示国内主要起飞机场的经纬度分布,点的大小映射机场累计乘客总量<br>
            2.  核心价值:直观呈现机场客流规模差异,为航空枢纽规划、运力调配提供参考<br>
            3.  可视化特点:多彩散点样式,标注清晰,可快速识别核心枢纽机场<br>
            4.  数据支撑:基于300+航班记录聚合计算,覆盖国内主流航空枢纽
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/route_analysis.html(修正HTML布局格式) --------------------
    os.path.join(PROJECT_ROOT, "templates", "route_analysis.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>航线分析 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 航线热度深度分析</h1>

        <h2 class="sub-title">一、核心可视化图表</h2>
        <div class="chart-grid">
            <!-- 前10航线航班数 -->
            <div class="chart-card">
                <h3 class="chart-title">前10条航线航班数排名</h3>
                <img src="{{ url_for('static', filename='images/top10_routes_count.png') }}" alt="航线航班数" class="chart-img">
            </div>

            <!-- 前10航线乘客数 -->
            <div class="chart-card">
                <h3 class="chart-title">前10条航线乘客总数排名</h3>
                <img src="{{ url_for('static', filename='images/top10_routes_passengers.png') }}" alt="航线乘客数" class="chart-img">
            </div>
        </div>

        <h2 class="sub-title">二、分析说明</h2>
        <p class="about-text">
            1.  航班数排名:反映航线的运营频次,体现航线的重要性与市场需求<br>
            2.  乘客数排名:反映航线的实际运输规模,是航线热度的核心指标<br>
            3.  差异分析:航班数与乘客数的排名差异,可体现单航班载客量的差异<br>
            4.  应用价值:为航空公司航线优化、票价调整提供数据支撑
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/airline_analysis.html(修正HTML样式引用) --------------------
    os.path.join(PROJECT_ROOT, "templates", "airline_analysis.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>航空公司分析 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 航空公司运营分析</h1>

        <h2 class="sub-title">一、核心可视化图表</h2>
        <div class="chart-grid">
            <!-- 航空公司准点率 -->
            <div class="chart-card">
                <h3 class="chart-title">各航空公司平均准点率</h3>
                <img src="{{ url_for('static', filename='images/airline_ontime.png') }}" alt="航空公司准点率" class="chart-img">
            </div>

            <!-- 航空公司票价箱线图 -->
            <div class="chart-card">
                <h3 class="chart-title">航空公司票价分布(箱线图)</h3>
                <img src="{{ url_for('static', filename='images/airline_price_box.png') }}" alt="航空公司票价" class="chart-img">
            </div>

            <!-- 机型占比饼图 -->
            <div class="chart-card" style="grid-column: span 2; max-width: 800px; margin: 0 auto;">
                <h3 class="chart-title">主要机型占比(前8)</h3>
                <img src="{{ url_for('static', filename='images/aircraft_type_pie.png') }}" alt="机型占比" class="chart-img">
            </div>
        </div>

        <h2 class="sub-title">二、分析说明</h2>
        <p class="about-text">
            1.  准点率分析:反映航空公司的运营效率,是服务质量的核心指标<br>
            2.  票价分布:展示各航空公司票价的区间、中位数及异常值,体现价格竞争力<br>
            3.  机型占比:反映航空公司机队构成,关联运力规模与运营成本<br>
            4.  综合价值:为旅客选择航空公司、航空公司优化机队提供参考
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/price_analysis.html(修正HTML图片引用格式) --------------------
    os.path.join(PROJECT_ROOT, "templates", "price_analysis.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>票价分析 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 航班票价深度分析</h1>

        <h2 class="sub-title">一、核心可视化图表</h2>
        <div class="chart-grid">
            <!-- 票价分布直方图 -->
            <div class="chart-card">
                <h3 class="chart-title">票价总体分布</h3>
                <img src="{{ url_for('static', filename='images/price_distribution.png') }}" alt="票价分布" class="chart-img">
            </div>

            <!-- 票价vs里程散点图 -->
            <div class="chart-card">
                <h3 class="chart-title">票价与飞行里程关系(带回归线)</h3>
                <img src="{{ url_for('static', filename='images/price_vs_mileage.png') }}" alt="票价与里程" class="chart-img">
            </div>
        </div>

        <h2 class="sub-title">二、分析说明</h2>
        <p class="about-text">
            1.  票价分布:呈现航班票价的集中区间,反映市场价格水平与差异度<br>
            2.  票价与里程:通过散点图+回归线,量化里程对票价的影响程度,体现"里程越长,票价越高"的规律<br>
            3.  异常值分析:票价分布中的异常值,可反映高端航线、特价机票等特殊情况<br>
            4.  应用价值:为旅客购票决策、航空公司定价策略提供数据支撑
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/time_analysis.html(修正HTML网格布局格式) --------------------
    os.path.join(PROJECT_ROOT, "templates", "time_analysis.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>时间分析 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">✈️ 航班时间维度分析</h1>

        <h2 class="sub-title">一、核心可视化图表</h2>
        <div class="chart-grid">
            <!-- 准点率vs里程 -->
            <div class="chart-card">
                <h3 class="chart-title">准点率与飞行里程关系</h3>
                <img src="{{ url_for('static', filename='images/ontime_vs_mileage.png') }}" alt="准点率与里程" class="chart-img">
            </div>

            <!-- 每周班期分布 -->
            <div class="chart-card">
                <h3 class="chart-title">每周各天有班期航班数</h3>
                <img src="{{ url_for('static', filename='images/weekday_schedule.png') }}" alt="每周班期" class="chart-img">
            </div>

            <!-- 起飞小时分布 -->
            <div class="chart-card" style="grid-column: span 2; max-width: 800px; margin: 0 auto;">
                <h3 class="chart-title">航班起飞小时分布(24小时制)</h3>
                <img src="{{ url_for('static', filename='images/departure_hour.png') }}" alt="起飞小时" class="chart-img">
            </div>
        </div>

        <h2 class="sub-title">二、分析说明</h2>
        <p class="about-text">
            1.  准点率与里程:分析飞行里程对航班准点率的影响,为旅客选择航线提供参考<br>
            2.  每周班期:呈现航班的周度分布规律,体现商务航线(工作日密集)与旅游航线(周末密集)的差异<br>
            3.  起飞小时:展示24小时内航班起飞的时段分布,反映机场运营高峰时段<br>
            4.  应用价值:为旅客选择出行时间、机场调度优化提供数据支撑
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>""",

    # -------------------- templates/about.html(修正HTML文本格式,无语法错误) --------------------
    os.path.join(PROJECT_ROOT, "templates", "about.html"): """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>关于系统 - 航班数据可视化系统</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav-bar">
        <div class="nav-container">
            <a href="/" class="nav-item">首页</a>
            <a href="/airport" class="nav-item">机场分析</a>
            <a href="/route" class="nav-item">航线分析</a>
            <a href="/airline" class="nav-item">航空公司</a>
            <a href="/price" class="nav-item">票价分析</a>
            <a href="/time" class="nav-item">时间分析</a>
            <a href="/about" class="nav-item">关于系统</a>
        </div>
    </div>

    <!-- 页面容器 -->
    <div class="container">
        <h1 class="page-title">📖 关于航班数据可视化系统</h1>

        <h2 class="sub-title">一、系统介绍</h2>
        <p class="about-text">
            本系统是基于Python+Flask构建的全国航班数据可视化平台,
            整合了Pandas、NumPy、Matplotlib等工具,实现了机场、航线、航空公司、票价、时间的多维度分析,
            生成11张高清可视化图表,并通过美观艳丽的多页面网页进行展示,支持自动生成图表与中文无乱码显示。
        </p>

        <h2 class="sub-title">二、核心技术栈</h2>
        <p class="about-text">
            1.  后端框架:Flask(轻量级Web框架,实现多页面路由与模板渲染)<br>
            2.  数据处理:Pandas、NumPy(数据清洗、指标计算、聚合统计)<br>
            3.  可视化:Matplotlib(生成高清多彩图表,支持多种图表类型)<br>
            4.  前端美化:CSS3(渐变背景、卡片布局、hover特效、响应式设计)
        </p>

        <h2 class="sub-title">三、功能亮点</h2>
        <p class="about-text">
            1.  多页面设计:首页、机场分析、航线分析、航空公司分析、票价分析、时间分析、关于页面,共7个页面<br>
            2.  高清可视化:11张不同类型图表(散点图、柱状图、箱线图、饼图等)<br>
            3.  美观样式:色彩艳丽的渐变背景、卡片悬浮特效、响应式布局,适配不同设备<br>
            4.  中文支持:全程中文显示,自动识别系统中文字体,解决乱码问题<br>
            5.  自动生成:启动系统时自动检测并生成图表,无需手动操作数据
        </p>
    </div>

    <!-- 页脚 -->
    <div class="footer">
        © 2026 航班数据可视化系统 | 基于Python+Flask开发
    </div>
</body>
</html>"""
}

# 3. 遍历写入所有文件(修正文件写入的编码和异常捕获格式)
for file_path, content in file_contents.items():
    try:
        # 确保目录存在(额外容错,避免目录未创建导致写入失败)
        file_dir = os.path.dirname(file_path)
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        print(f"成功写入文件:{file_path}")
    except Exception as e:
        print(f"写入文件失败 {file_path},错误信息:{str(e)}")

print("\n✅ 所有项目目录和文件创建完成!")
print(f"📁 项目根目录:{os.path.abspath(PROJECT_ROOT)}")
print("📋 后续运行步骤:")
print(f"  1.  进入项目目录:cd {PROJECT_ROOT}")
print("  2.  放入航班数据文件:将Excel数据文件放入项目根目录(可选,无则自动生成示例数据)")
print("  3.  安装依赖:pip install -r requirements.txt")
print("  4.  启动服务:python app.py(自动生成图表)")
print("  5.  浏览器访问:http://localhost:5000")

多模型实验对比分析图模板

# pv_deterministic_predictions.py
# Purpose: Based on the provided PV power series, generate multi-model predictions with deterministic patterns (no random numbers),
# and plot comparison charts, save predictions and evaluation metrics (CSV).
#
# Dependencies: numpy pandas matplotlib seaborn scikit-learn
# Run: python pv_deterministic_predictions.py
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']   # Or 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pathlib import Path
from sklearn.metrics import mean_squared_error, r2_score
from mpl_toolkits.axes_grid1.inset_locator import inset_axes, mark_inset

# ----------------- Configuration -----------------
OUTDIR = Path("outputs")
OUTDIR.mkdir(exist_ok=True)
PNG_PATH = OUTDIR / "pv_deterministic_combined.png"
SVG_PATH = OUTDIR / "pv_deterministic_combined.svg"
DPI = 300
SMALL = 1e-9


# ---------- True power series (kW) ----------
y_raw = np.array([
1.869785143,1.424279785,3.284687839,4.469799654,4.641674298,2.903635736,2.875670767,3.023249843,
3.960831064,6.292840247,7.490782871,7.188161552,5.083116459,7.555337324,8.026012375,7.756679639,
6.502993161,8.007372755,8.25701376,8.693322864,9.366570089,8.434015061,8.228560733,9.452560641,
9.641931754,9.992432266,9.898516804,9.910650888,10.12202469,9.956782737,10.24027585,10.40329107,
10.78140284,10.73177983,10.69464896,10.71354887,10.63098439,10.5550337,10.50013456,10.72825244,
11.49781215,9.485727848,10.74798907,10.57457674,10.66129499,9.13621384,5.812934732,10.93896937,
2.418341001,7.661125681,6.158808587,9.31396986,7.492579232,3.045420944,2.328612075,8.885645573,
8.544524655,3.475986079,9.621451871,4.659551051,5.471063028,2.97880716,2.541289817,3.945203344,
4.905153777,8.708233167,8.452653687,8.40228087,4.171490675,2.33975314,7.234123703,7.330922064,
7.471947966,6.111903713,7.173188774,6.342575227,3.50410543,2.475409423,3.533937407,5.696707056,
4.907186059,4.498276012,4.483758233,4.813505703,4.850329586,4.551778675,3.71990452,2.926004469,
2.422037177,2.451192401,2.381123992,2.152501012,1.699547264,1.654904957,1.226836388,0.379993053,
1.756545256,1.819448963,1.874411096,2.808044262,3.173711246,3.417027727,3.609300824,3.900914411,
4.287242158,4.882292338,4.923661312,4.908430755,5.167656896,4.813427919,4.95720893,4.895259861,
4.468547989,4.137617403,4.13968683,3.873263561,3.537147605,3.593079673,3.393744438,3.513882092,
3.350616212,3.207234883,3.201310962,3.357771805,3.30694307,3.519563074,3.505726649,3.784583563,
4.029632745,4.183464796,4.06075168,3.926208516,2.964022277,2.724872562,2.777032939,2.18916268,
1.84178962,1.617030318,4.284615404,4.210232313,4.15615083,3.355271149,3.500488614,3.8400196,
4.315650784,2.594142666,2.395414222,1.78445305,1.76754006,1.929501887,2.992962864,4.051325535,
2.544299112,2.296236423,3.526954124,1.75716029,1.241286292,3.173010673,1.211392469,1.20511285,
1.406620306,1.691278773,1.825291854,2.004346118,1.653866,1.706801669,1.761233604,1.738620349,
1.986290121,1.842643054,1.832435757,1.520278324,1.363951086,1.1133274,0.521741078,0.758958274,
0.805574102,1.011010109,1.18979168,1.058402875,1.232446371,1.318971024,0.973771519,1.322578191,
1.118047204,1.036458987,0.983608278,0.902925899,0.999939019,0.818567393,0.809813734,0.84893486,
0.784031989,0.680703547,0.676498661,0.827448579,0.775926731,0.518055455,0.712152869,0.522645613,
0.560175999,0.46238014,0.51905107,0.789826853,0.861304495,0.87134296,1.056604452,1.051989367,
0.924917554,0.883926908,0.586064908,1.014996145,0.840648289,0.455198117,0.760450498,1.606300687,
1.664827083,1.545949244,1.334052316,1.438577939,2.330545029,2.494461269,2.592446504,2.324591071,
2.289294347,2.408096346,2.162543156,2.375641305,1.893522403,1.953715421,1.795597189,1.93105813,
1.819684532,0.903336276,1.240459775,1.168571749,1.16575022,1.458535788,1.744210058,1.969624484,
2.025528101,2.205104991,2.345402068,2.31455667,2.401690506,1.747502001,1.036820781,1.410063427,
1.17391423,1.259477079,1.150328388,1.029521481,1.005999676,1.293637268,1.37235313,0.658296563,
0.726618345,0.711905808,0.76297487,0.690171819,0.496502651,0.595898615,0.875244862,0.808055772,
0.531230301,0.574425987,0.409708942,0.619248427,0.672596486,0.571319133,0.634278328,0.576760316,
0.417260588,0.369732249,0.318806357,0.25496991,0.460322079,0.114634642,0.355731299,0.482881892,
0.304061945,0.335742416,0.336089939,0.300504868,0.474440651,0.350594159,0.414627438,0.498926929,
0.091987278,0.14681018,0.145059034,0.084446735,0.150430953,0.460568612,0.1522849,0.047586657,
0.175210812,0.066983156,0.379993053,3.24458527,3.35192714,3.497858665,3.633904459,3.880571796,
4.306213784,4.401638978,4.88823669,5.174956818,5.253997066,5.779475107,5.63796096,5.82083903,
5.935189,5.922387884,6.375044181,6.61502453,6.766662592,7.103964489,7.281926083,7.366053377,
7.664569182,8.404781552,8.098115478,8.44610354,8.627429508,8.634414329,8.925193964,8.948053285,
9.461745786,9.541923424,9.478042083,9.730247823,9.939220483,10.09680878,10.15566165,10.25247728,
10.31576012,10.57531781,10.57352398,10.77607047,10.69061591,10.70639479,10.57987417,10.69766906,
10.74040338,10.74030532,10.82943508,10.7378987,10.9213605,11.00226719,10.85615586,10.86595489,
10.76111612,10.84553852,10.92105884,10.89200738,10.87589064,10.77534963,10.8488072,10.68775945,
10.69860025,10.62177213,10.64421387,10.59296547,10.54670355,10.11126911,10.00001901,9.89002469,
9.532107957,9.583007719,9.283132671,9.284315271,9.016888605,8.737283536,8.656885775,8.522125037,
8.102514006,7.871427181,7.917606259,7.661141515,7.541905386,7.311937358,6.662914989,6.244124036,
5.97817395,5.801644722,5.512220098,5.500855947,5.38391588,4.608453712,4.680071178,4.447526335,
4.166744817,4.027087989,3.832874285,3.399302223,3.393088053,3.196242414,2.919100475,2.779335843,
2.408000491,2.284672953,1.88307251,1.618184921,1.58804384,1.413498624,0.379993053,3.329216201,
3.815873378,4.131831963,4.521564193,4.60996529,4.645545777,4.795147439,4.878963905,4.774383314,
5.483833174,5.51368295,5.591262947,5.743607245,5.85943184,6.093228786,6.114847304,6.352042877,
6.503909795,6.678675181,7.024902064,7.733771266,7.930167217,7.977470234,8.165776544,8.477550339,
8.607431552,9.023670683,8.989584832,9.534435843,9.567524346,9.494248731,9.523650599,9.697715485,
9.714543113,9.634695252,9.71850881,9.821361226,9.980882515,10.29491443,10.11851947,10.1175718,
10.34630592,10.18127725,10.22317014,10.35613762,10.24646686,10.27057375,10.48176377,10.39622627,
10.29630452,10.12110712,9.999450448,9.967171894,10.2856697,9.605797382,9.850959435,7.004241015,
8.736486263,9.761746543,9.939029493,9.990341117,10.19642154,10.43026091,9.55804554,9.179217981,
0.379993053
], dtype=float)

n = len(y_raw)
x = np.arange(n)

# ---------------- Common signal processing functions (deterministic) ----------------
def moving_average(a, w):
    if w <= 1:
        return a.copy()
    kernel = np.ones(w) / w
    # pad to keep same length with edge reflection to reduce edge effect
    pad = w//2
    a_pad = np.pad(a, pad, mode='reflect')
    conv = np.convolve(a_pad, kernel, mode='valid')
    return conv[:n]

def lag_signal(a, lag):
    if lag == 0:
        return a.copy()
    if lag > 0:
        return np.concatenate([np.full(lag, a[0]), a[:-lag]])
    else:
        # negative lag => lead
        lag = -lag
        return np.concatenate([a[lag:], np.full(lag, a[-1])])

def local_trend(a, window=5):
    # Local trend = difference between current point and local moving average
    ma = moving_average(a, window)
    return a - ma

# ---------------- Generate "deterministic" model predictions ----------------
preds = {}

# 1) LSTM: Moderate smoothing + Systematic underestimation of peaks (scaling factor <1) + Small lag
ma_short = moving_average(y_raw, 5)
lstm = 0.97 * lag_signal(ma_short, lag=1)  # Slightly lagged and scaled down
# Apply additional suppression in peak regions (simulate LSTM's conservative prediction in extreme moments)
peak_mask = y_raw > (0.9 * y_raw.max())
lstm[peak_mask] *= 0.95
preds['LSTM'] = lstm

# 2) GRU: Slightly smoothing + Obvious lag (model response delay to cloud cover recovery)
ma_med = moving_average(y_raw, 3)
gru = lag_signal(ma_med, lag=2) * 0.985
# GRU responds slowly to rapid increases: reduce appropriately in rising segments
rise = np.maximum(0, y_raw - moving_average(y_raw, 8))
gru += 0.02 * (rise) * 0  # Keep deterministic but don't add random terms (reserved format)
preds['GRU'] = gru

# 3) Transformer: Large window smoothing + Maintain global magnitude (less lag)
ma_long = moving_average(y_raw, 11)
transformer = 0.995 * ma_long + 0.005 * y_raw  # Maintain global trend while retaining partial original
preds['Transformer'] = transformer

# 4) ARMA-BP: Linear autoregressive term + local residual approximated by small window mean (deterministic)
# Simple first-order autoregression: pred_t = alpha * y_{t-1} + (1-alpha)*local_ma
alpha = 0.88
local_ma3 = moving_average(y_raw, 3)
y_prev = lag_signal(y_raw, 1)
arma_bp = alpha * y_prev + (1 - alpha) * local_ma3
# BP compensation: add 30% of local trend correction
arma_bp += 0.30 * local_trend(y_raw, window=5)
preds['ARMA-BP'] = arma_bp

# 5) GA-AMODE-BiLSTM: Assume optimized hyperparameters through evolutionary methods => Balanced bidirectional information, almost no lag but slight scaling
bilstm = 0.99 * (0.5 * moving_average(y_raw, 3) + 0.5 * moving_average(y_raw, 9))
# Minor correction to better match peaks (simulate hyperparameter tuning)
bilstm += 0.02 * np.maximum(0, (y_raw - moving_average(y_raw, 7)))
preds['GA-AMODE-BiLSTM'] = bilstm

# 6) MSCT: Multi-scale convolution + Transformer fusion - Most accurate to reality
msct_short = moving_average(y_raw, 3)
msct_mid = moving_average(y_raw, 7)
msct_long = moving_average(y_raw, 15)
# Weighted fusion (short:mid:long = 0.35:0.35:0.3), add local difference correction to capture high-frequency fluctuations
msct = 0.35 * msct_short + 0.35 * msct_mid + 0.3 * msct_long
# Local difference correction (small coefficient)
msct += 0.06 * local_trend(y_raw, window=5)
# Reduce correction in low-value regions (avoid negative values or overfitting noise)
msct = np.clip(msct, 0.0, None)
preds['MSCT'] = msct

# --------- Ensure prediction arrays have consistent length and are float ---------
for k in list(preds.keys()):
    preds[k] = np.asarray(preds[k], dtype=float)
    assert preds[k].shape[0] == n

# ----------------- Calculate evaluation metrics (physical unit kW) -----------------
def compute_metrics(true, pred):
    mse = mean_squared_error(true, pred)
    rmse = np.sqrt(mse)
    mae = np.mean(np.abs(true - pred))
    eps = SMALL
    mape = np.mean(np.abs((true - pred) / np.maximum(np.abs(true), eps))) * 100.0
    r2 = r2_score(true, pred)
    return {'MSE': mse, 'RMSE': rmse, 'MAE': mae, 'MAPE': mape, 'R2': r2}

metrics_list = []
for name, p in preds.items():
    m = compute_metrics(y_raw, p)
    m['Model'] = name
    metrics_list.append(m)
metrics_df = pd.DataFrame(metrics_list).set_index('Model')

# Print metrics (for quick viewing)
print("=== Evaluation metrics (kW / %) ===")
print(metrics_df.round(4))

# ----------------- Save predictions and metrics -----------------
pred_df = pd.DataFrame({'time_index': x, 'true_power': y_raw})
for name, p in preds.items():
    pred_df[f'pred_{name}'] = p
pred_df.to_csv(OUTDIR / "predictions_deterministic_models.csv", index=False)
metrics_df.to_csv(OUTDIR / "metrics_deterministic_models.csv")

# ----------------- Plotting (main plot + inset) -----------------
plt.figure(figsize=(11, 6.5))
ax = plt.gca()

# Main curve: true power (black thick line)
ax.plot(x, y_raw, color="black", linewidth=2.2, label="True Power")

# Color palette and line styles
palette = sns.color_palette("tab10", n_colors=len(preds))
linestyles = ["--", "-.", ":", "-", (0, (3,1,1,1)), (0, (1,1))]
for (name, p), col, ls in zip(preds.items(), palette, linestyles):
    ax.plot(x, p, label=name, linewidth=1.4, linestyle=ls, alpha=0.95)

# Find knee (maximum relative drop) for inset zoom
y_diff = np.diff(y_raw)
knee_idx = int(np.argmax(-y_diff)) + 1
zoom_half = 60
z0 = max(0, knee_idx - zoom_half)
z1 = min(n, knee_idx + zoom_half)

# Threshold line example (optional)
ax.axhline(y_raw.max() * 0.5, color="gray", linestyle="--", linewidth=0.9, alpha=0.6)
ax.text(3, y_raw.max()*0.5 + 0.12, f"Reference = {y_raw.max()*0.5:.2f} kW", color="gray", fontsize=9)

# Titles and axes
ax.set_title("PV Power Generation: True vs Multi-Model (Deterministic) Predictions", fontsize=14, weight='bold')
ax.set_xlabel("Time Index", fontsize=11)
ax.set_ylabel("Power (kW)", fontsize=11)

# Beautify legend: inset, semi-transparent background
leg = ax.legend(loc="upper left", bbox_to_anchor=(0.02, 0.98), frameon=True, fontsize=9)
leg.get_frame().set_alpha(0.92)
leg.get_frame().set_boxstyle("round,pad=0.4")

# Inset zoom on knee region
axins = inset_axes(ax, width="44%", height="36%", loc='lower right',
                  bbox_to_anchor=(0.02,0.02,0.96,0.96), bbox_transform=ax.transAxes)
axins.plot(x[z0:z1], y_raw[z0:z1], color="black", linewidth=2.0)
for (name, p), col in zip(preds.items(), palette):
    axins.plot(x[z0:z1], p[z0:z1], linewidth=1.2, alpha=0.95)
axins.set_xlim(z0, z1)
axins.tick_params(labelsize=8)
axins.grid(True, linewidth=0.4, alpha=0.5)
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.45")

# Minor grid, border adjustments
ax.grid(True, linestyle='--', linewidth=0.5, alpha=0.45)
for spine in ax.spines.values():
    spine.set_linewidth(0.8)

# Bottom-right table (MAE, RMSE, MAPE, R2)
table_lines = []
for name, row in metrics_df.iterrows():
    table_lines.append(f"{name}: MAE={row['MAE']:.3f}  RMSE={row['RMSE']:.3f}  MAPE={row['MAPE']:.2f}%  R²={row['R2']:.3f}")
table_text = "\n".join(table_lines)
ax.text(0.99, 0.06, table_text, transform=ax.transAxes, fontsize=9,
        verticalalignment='bottom', horizontalalignment='right',
        bbox=dict(facecolor='white', alpha=0.85, edgecolor='none'))

plt.tight_layout()
plt.savefig(PNG_PATH, dpi=DPI, bbox_inches='tight')
plt.savefig(SVG_PATH, bbox_inches='tight')
plt.show()

print("Saved:", PNG_PATH, SVG_PATH)
print("Predictions saved to:", OUTDIR / "predictions_deterministic_models.csv")
print("Metrics saved to:", OUTDIR / "metrics_deterministic_models.csv")

显示目标检测目录格式

import os


def count_files_and_folders(folder_path):
    """统计指定文件夹内的【文件数量】和【子文件夹数量】"""
    file_count = 0
    folder_count = 0
    for name in os.listdir(folder_path):
        full_path = os.path.join(folder_path, name)
        if os.path.isdir(full_path):
            folder_count += 1
        else:
            file_count += 1
    return folder_count, file_count


def print_folder_tree_with_count(folder_path, prefix=""):
    """递归打印【仅文件夹】树形结构 + 子文件夹/文件数量统计"""
    folder_list = sorted([
        name for name in os.listdir(folder_path)
        if os.path.isdir(os.path.join(folder_path, name))
    ])

    for index, folder_name in enumerate(folder_list):
        folder_full_path = os.path.join(folder_path, folder_name)
        is_last_folder = index == len(folder_list) - 1

        if is_last_folder:
            tree_symbol = "└── "
            next_prefix = prefix + "    "
        else:
            tree_symbol = "├── "
            next_prefix = prefix + "│   "

        # 统计当前文件夹的子文件夹数、文件数
        sub_folder_num, file_num = count_files_and_folders(folder_full_path)
        # 打印:文件夹 + 统计信息
        print(f"{prefix}{tree_symbol}📁 {folder_name}  (子文件夹: {sub_folder_num} | 文件数: {file_num})")
        # 递归遍历子文件夹
        print_folder_tree_with_count(folder_full_path, next_prefix)


if __name__ == "__main__":
    root_dir = os.path.dirname(os.path.abspath(__file__))
    print("=" * 70)
    print(f"📂 数据集根目录:{root_dir}")
    print("=" * 70)
    print("📊 crack_dataset_en【纯文件夹】目录结构 + 数量统计(无文件):\n")
    print_folder_tree_with_count(root_dir)

import os


def print_folder_tree(folder_path, prefix=""):
    """递归打印【仅文件夹】的树形目录结构,不显示任何文件"""
    # 筛选出当前目录下【所有文件夹】,排除所有文件,按名称排序
    folder_list = sorted([
        name for name in os.listdir(folder_path)
        if os.path.isdir(os.path.join(folder_path, name))
    ])

    # 遍历所有文件夹,生成标准树形结构
    for index, folder_name in enumerate(folder_list):
        folder_full_path = os.path.join(folder_path, folder_name)
        # 判断是否是当前目录下最后一个文件夹,控制树形符号
        is_last_folder = index == len(folder_list) - 1

        if is_last_folder:
            tree_symbol = "└── "
            next_prefix = prefix + "    "  # 最后一个文件夹,后续缩进用空格
        else:
            tree_symbol = "├── "
            next_prefix = prefix + "│   "  # 非最后一个,后续缩进用竖线,保持结构对齐

        # 打印文件夹名称+图标
        print(f"{prefix}{tree_symbol}📁 {folder_name}")
        # 递归打印子文件夹
        print_folder_tree(folder_full_path, next_prefix)


if __name__ == "__main__":
    # 获取当前脚本所在的【数据集根目录】绝对路径
    root_dir = os.path.dirname(os.path.abspath(__file__))
    print("=" * 70)
    print(f"📂 数据集根目录:{root_dir}")
    print("=" * 70)
    print("📊 crack_dataset_en【纯文件夹】目录树形结构(无文件):\n")
    # 执行打印
    print_folder_tree(root_dir)
import os
import time


def get_file_size(size_byte):
    """字节转KB/MB,格式化文件大小"""
    if size_byte < 1024:
        return f"{size_byte} B"
    elif size_byte < 1024 * 1024:
        return f"{round(size_byte / 1024, 2)} KB"
    else:
        return f"{round(size_byte / (1024 * 1024), 2)} MB"


def print_dir_tree_detail(folder_path, prefix=""):
    """递归打印树形结构 + 文件详细信息"""
    file_list = sorted(os.listdir(folder_path), key=lambda x: (not os.path.isdir(os.path.join(folder_path, x)), x))
    for index, file_name in enumerate(file_list):
        file_path = os.path.join(folder_path, file_name)
        is_last = index == len(file_list) - 1

        if is_last:
            symbol = "└── "
            next_prefix = prefix + "    "
        else:
            symbol = "├── "
            next_prefix = prefix + "│   "

        if os.path.isdir(file_path):
            # 文件夹信息
            print(f"{prefix}{symbol}📁 【文件夹】 {file_name}")
            print_dir_tree_detail(file_path, next_prefix)
        else:
            # 文件详细信息
            file_size = get_file_size(os.path.getsize(file_path))
            modify_time = time.strftime("%Y-%m-%d %H:%M", time.localtime(os.path.getmtime(file_path)))
            print(f"{prefix}{symbol}📄 【文件】 {file_name} | 大小:{file_size} | 修改时间:{modify_time}")


if __name__ == "__main__":
    root_dir = os.path.dirname(os.path.abspath(__file__))
    print("=" * 80)
    print(f"📂 数据集根目录:{root_dir}")
    print("=" * 80)
    print(f"📊 数据集树形结构 + 文件详细信息:\n")
    print_dir_tree_detail(root_dir)

更多推荐