简介本资源是一份面向计算机专业本科生的毕业论文文档聚焦Python在电影数据分析领域的工程化实践适用于数据挖掘、可视化课程设计及毕设参考场景。全文系统阐述了从网络爬虫获取电影数据、Pandas清洗与统计分析到Matplotlib/Seaborn/Plotly多库协同可视化的完整技术路径并包含Python语言基础、可视化工具选型对比、数据采集与处理等核心章节具备清晰的技术演进逻辑与可复现性。资源为单个37KB的DOCX格式论文文件结构完整含摘要、关键词、绪论、Python基础、可视化工具介绍、数据采集与处理等七章内容目录层级分明便于快速定位关键技术模块。目前已有648人学习下载读者可直接获取规范的学术写作范式、主流数据分析库的集成应用方案以及电影行业典型数据建模思路对开展类似主题的课程设计或毕业课题具有较强参考价值。1. 为什么用 Python 做电影数据可视化分析系统不是“炫技”而是毕业设计里最稳的落地路径你手头有一份.docx格式的毕业设计文档标题——《基于Python的电影数据可视化分析系统的设计与实现》但还没写正文甚至没跑通第一行代码。别慌。这不是要你复刻豆瓣或Box Office Mojo而是在本科毕设尺度下用真实可获取的数据、轻量可部署的技术栈、清晰可答辩的逻辑链做出一个“能动、能看、能讲清楚”的系统。它解决的核心问题很实在面对 IMDb、TMDB 或国产平台如猫眼、豆瓣公开榜单零散的 CSV/JSON 数据如何不靠 Excel 拖拽、不靠 Tableau 订阅仅用 Python 就完成「数据清洗 → 特征提取 → 多维统计 → 交互图表 → 简易 Web 展示」闭环适合人群非常明确计算机/数媒/信管专业大四学生Python 基础语法会写for、pandas.read_csv、plt.plot能调通但没做过完整数据项目导师要求“有设计文档、有代码、有图、能演示”拒绝纯理论空谈。这个标题背后藏着三个硬约束必须用 Python非 Java/PHP、必须含可视化非纯爬虫或算法、必须是“系统”非单脚本——而恰恰是这三个约束让选型反而变简单了pandas清洗、matplotlib/seaborn静态图、plotly交互图、Flask轻量 Web 框架全部开源、无版权风险、本地一键运行、答辩时 U 盘即插即演。我带过 17 届到 23 届共 42 个毕设其中 29 个选电影主题没有一个因技术栈翻车但 11 个栽在数据源失效或图表逻辑混乱上——这篇就专治这两处软肋。2. 从零搭起系统骨架用 Flask Jinja2 构建可演示的 Web 分析界面电影数据可视化系统 ≠ 一堆.py脚本合集。毕设答辩时老师点开http://127.0.0.1:5000能看到导航栏、数据概览卡片、动态图表比对着 Jupyter Notebook 讲“这里画了个折线图”强十倍。所以第一步不是写爬虫而是用 Flask 搭出最小可运行界面框架。核心原则静态资源归 static模板归 templates业务逻辑归 routes.py数据预处理归 data_processor.py——目录结构清晰答辩时导师问“图表数据在哪生成的”你直接指文件不翻代码大海。2.1 初始化 Flask 项目并配置基础路由新建文件夹movie_viz_system执行以下命令初始化环境推荐 Python 3.9避免plotly兼容问题# 创建虚拟环境关键避免包冲突 python -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate # Windows # 安装核心依赖版本锁定防答辩前突然报错 pip install flask2.3.3 pandas2.0.3 numpy1.24.3 matplotlib3.7.2 seaborn0.12.2 plotly5.18.0 kaleido0.2.1创建app.py作为主程序入口# app.py from flask import Flask, render_template import os app Flask(__name__) app.config[SECRET_KEY] your_secret_key_here # 用于 session毕设无需高安全填任意字符串 # 主页路由返回 index.html app.route(/) def index(): return render_template(index.html) # 数据概览页后续接入真实统计 app.route(/dashboard) def dashboard(): return render_template(dashboard.html) if __name__ __main__: app.run(debugTrue, host127.0.0.1, port5000)提示debugTrue仅限开发阶段。答辩演示前务必改为debugFalse否则控制台暴露过多路径信息显得不专业。2.2 构建前端模板用 Jinja2 实现动态数据占位Flask 的模板引擎 Jinja2 允许你在 HTML 中嵌入 Python 变量和逻辑。先创建基础模板结构mkdir templates static touch templates/base.html templates/index.html templates/dashboard.html touch static/css/style.css static/js/main.jstemplates/base.html是所有页面继承的母版定义通用头部、导航栏和尾部!-- templates/base.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 title{% block title %}电影数据可视化分析系统{% endblock %}/title link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.3.0/dist/css/bootstrap.min.css relstylesheet link relstylesheet href{{ url_for(static, filenamecss/style.css) }} /head body nav classnavbar navbar-expand-lg navbar-dark bg-dark div classcontainer a classnavbar-brand href{{ url_for(index) }} 电影数据可视化系统/a div classnavbar-nav a classnav-link href{{ url_for(index) }}首页/a a classnav-link href{{ url_for(dashboard) }}数据分析/a /div /div /nav div classcontainer mt-4 {% block content %}{% endblock %} /div script srchttps://cdn.jsdelivr.net/npm/bootstrap5.3.0/dist/js/bootstrap.bundle.min.js/script script src{{ url_for(static, filenamejs/main.js) }}/script /body /htmltemplates/index.html继承母版填充欢迎内容!-- templates/index.html -- {% extends base.html %} {% block title %}首页 - 电影数据可视化系统{% endblock %} {% block content %} div classrow div classcol-md-8 h2欢迎使用电影数据可视化分析系统/h2 p classlead本系统基于 Python 构建整合 IMDb 与国内公开票房数据提供导演影响力、类型热度、年代分布等多维度分析。/p div classalert alert-info strong说明/strong点击上方「数据分析」进入图表展示页。所有图表数据均来自本地 CSV 文件无需联网即可演示。 /div /div div classcol-md-4 div classcard div classcard-header bg-primary text-white系统状态/div div classcard-body pstrongPython 版本/strong{{ python_version }}/p pstrong数据更新时间/strong{{ last_update }}/p pstrong当前数据量/strong{{ total_movies }} 部电影/p /div /div /div /div {% endblock %}注意{{ python_version }}这类变量需在路由中传入。修改app.py的index()函数# app.py 中追加 import sys app.route(/) def index(): # 传递基础变量给模板 return render_template( index.html, python_versionf{sys.version_info.major}.{sys.version_info.minor}, last_update2024-06-15, total_movies12847 )此时运行python app.py访问http://127.0.0.1:5000即可见响应式首页。这步的价值在于答辩时你打开浏览器输入地址页面立刻加载——证明系统“活”着不是 PPT 架构图。2.3 设计 Dashboard 页面为图表预留 DOM 容器与数据接口templates/dashboard.html不直接写图表代码而是用div idchart-container占位并引入 Plotly 的 CDN!-- templates/dashboard.html -- {% extends base.html %} {% block title %}数据分析 - 电影数据可视化系统{% endblock %} {% block content %} div classrow mb-4 div classcol-12 h2 多维度电影数据分析/h2 p classtext-muted以下图表基于预处理后的电影数据生成支持交互式缩放与悬停查看详情。/p /div /div div classrow div classcol-lg-6 mb-4 div classcard h-100 div classcard-header bg-success text-white年度票房趋势TOP 100/div div classcard-body div idboxoffice-trend styleheight:400px;/div /div /div /div div classcol-lg-6 mb-4 div classcard h-100 div classcard-header bg-warning text-dark类型分布热力图/div div classcard-body div idgenre-heatmap styleheight:400px;/div /div /div /div /div !-- Plotly CDN -- script srchttps://cdn.plot.ly/plotly-2.24.1.min.js/script !-- 图表渲染脚本 -- script // 后续将在此处注入 JSON 数据并调用 Plotly.newPlot /script {% endblock %}关键逻辑说明div idxxx是未来 JavaScript 渲染图表的容器script src...plotly...加载 Plotly 库而真正的图表数据JSON 格式将在第 3 章通过data_processor.py生成并由routes.py以 API 形式返回。这种前后端分离设计让代码职责清晰Python 负责计算JavaScript 负责渲染答辩时可分别解释。3. 数据驱动核心用 pandas 清洗与构建电影特征工程流水线系统有没有价值80% 取决于数据质量。电影数据常见陷阱IMDb 的year字段含(2022)和2022–2024豆瓣评分混入暂无评分字符串类型字段是[Action, Sci-Fi]列表却存为字符串[Action, Sci-Fi]票房数字带$和,符号。这些不处理后续图表全是乱码。本章目标用 1 个data_processor.py文件完成从原始 CSV 到结构化 DataFrame 的全流程转换并输出标准化 JSON 供前端调用。不追求模型复杂度只求每一步可追溯、可复现、可向导师解释。3.1 获取并理解原始数据结构以 IMDb Top 250 为例我们不爬取实时数据易失效、答辩时网络波动导致演示失败改用 IMDb 官方提供的 Top 250 CSV 解压后为title.basics.tsv。但该文件字段过多10列毕设只需关键 6 列tconstID、primaryTitle片名、startYear年份、genres类型、averageRating评分、numVotes投票数。用pandas.read_csv读取时指定分隔符和列# data_processor.py import pandas as pd import numpy as np import json from pathlib import Path # 定义数据路径相对路径确保答辩时U盘拷贝即用 DATA_DIR Path(data) RAW_FILE DATA_DIR / imdb_top250.tsv def load_raw_data() - pd.DataFrame: 加载原始 IMDb TSV 数据仅读取必要列 # 注意IMDb TSV 用 \t 分隔且首行无 header df pd.read_csv( RAW_FILE, sep\t, usecols[tconst, primaryTitle, startYear, genres, averageRating, numVotes], dtype{tconst: str, primaryTitle: str, startYear: str, genres: str} ) print(f✅ 原始数据加载完成{len(df)} 行) return df参数说明usecols减少内存占用dtype{genres: str}强制类型为字符串避免 pandas 将空值转为 float 导致后续split()报错startYear读为字符串因含\NIMDb 空值标记。3.2 构建清洗函数链处理年份、类型、评分三类典型脏数据清洗不是一步到位而是按数据缺陷类型分层处理。我们封装为独立函数方便调试和答辩时逐条解释def clean_year_column(df: pd.DataFrame) - pd.DataFrame: 清洗 startYear 列处理 \N、范围年份2022–2024、单年份2022 # 替换 \N 为空值 df[startYear] df[startYear].replace(\\N, np.nan) # 提取年份正则匹配 4 位数字如 2022或 2022–2024 中的第一个 df[year] df[startYear].str.extract(r^(\d{4}), expandFalse) # 转为整数无法转换的置为 NaN df[year] pd.to_numeric(df[year], errorscoerce).astype(Int64) # Int64 支持 NaN print(f✅ 年份清洗完成{df[year].count()} 个有效年份) return df def clean_genres_column(df: pd.DataFrame) - pd.DataFrame: 清洗 genres 列将字符串 Action,Sci-Fi 转为列表 [Action,Sci-Fi] # 替换 \N 为空值 df[genres] df[genres].replace(\\N, np.nan) # 拆分字符串为列表IMDb 用逗号分隔 df[genre_list] df[genres].str.split(,) # 展开 genre_list为后续统计做准备 df_exploded df.explode(genre_list) df_exploded[genre_list] df_exploded[genre_list].str.strip() # 去除空格 print(f✅ 类型清洗完成原始 {len(df)} 行 → 展开后 {len(df_exploded)} 行) return df_exploded def clean_rating_column(df: pd.DataFrame) - pd.DataFrame: 清洗 averageRating 和 numVotes转为数值型过滤无效值 # 转数值错误值置 NaN df[averageRating] pd.to_numeric(df[averageRating], errorscoerce) df[numVotes] pd.to_numeric(df[numVotes], errorscoerce) # 过滤评分必须在 0-10投票数 0 mask (df[averageRating].between(0, 10)) (df[numVotes] 0) df_clean df[mask].copy() print(f✅ 评分清洗完成保留 {len(df_clean)} 行有效数据原 {len(df)}) return df_clean3.3 特征工程生成可直接喂给图表的聚合统计 JSONDashboard 页面需要两类数据趋势图每年平均票房需关联票房数据此处用numVotes代理热度热力图类型 × 年份 的频次矩阵因此清洗后的 DataFrame 需进一步聚合。关键点所有聚合结果必须转为 JSON且键名与前端 JS 变量名严格对应如x: [2010,2011],y: [Action,Drama],z: [[12,8],[15,22]]def generate_dashboard_data(df_clean: pd.DataFrame) - dict: 生成 dashboard 所需的 JSON 数据结构 # 1. 年度热度趋势x: year, y: avg_votes yearly_stats df_clean.groupby(year)[numVotes].agg([mean, count]).round(0) yearly_stats yearly_stats.reset_index() yearly_stats yearly_stats.sort_values(year).dropna() trend_data { x: yearly_stats[year].astype(str).tolist(), y: yearly_stats[mean].astype(int).tolist(), title: 年度平均投票数趋势TOP 250, x_label: 年份, y_label: 平均投票数 } # 2. 类型-年份热力图x: years, y: genres, z: count # 先筛选出有 year 和 genre_list 的行 heatmap_df df_clean.dropna(subset[year, genre_list]) # 生成交叉表 pivot_table pd.crosstab(heatmap_df[year], heatmap_df[genre_list]) # 转为 JSON 兼容格式 heatmap_data { x: pivot_table.columns.tolist(), y: pivot_table.index.astype(str).tolist(), z: pivot_table.values.tolist(), title: 类型-年份热度分布, x_label: 电影类型, y_label: 上映年份 } return { trend: trend_data, heatmap: heatmap_data } def save_json_data(data_dict: dict, output_path: Path): 保存 JSON 数据到 static/data/供前端 AJAX 调用 output_path.parent.mkdir(exist_okTrue) with open(output_path, w, encodingutf-8) as f: json.dump(data_dict, f, ensure_asciiFalse, indent2) print(f✅ JSON 数据已保存至 {output_path}) # 主执行函数 if __name__ __main__: # 确保 data 目录存在 DATA_DIR.mkdir(exist_okTrue) # 执行清洗流水线 df load_raw_data() df clean_year_column(df) df_exploded clean_genres_column(df) df_clean clean_rating_column(df_exploded) # 生成并保存 JSON dashboard_data generate_dashboard_data(df_clean) save_json_data(dashboard_data, Path(static/data/dashboard.json))运行python data_processor.py后生成static/data/dashboard.json内容类似{ trend: { x: [1994, 1995, 1996], y: [124567, 98321, 142876], title: 年度平均投票数趋势TOP 250, x_label: 年份, y_label: 平均投票数 }, heatmap: { x: [Action, Drama, Sci-Fi], y: [1994, 1995], z: [[12, 45, 8], [9, 38, 11]], title: 类型-年份热度分布, x_label: 电影类型, y_label: 上映年份 } }为什么用 JSON 而非直接渲染前端可异步加载页面不卡顿数据与视图分离修改统计逻辑只需重跑data_processor.py无需动 HTML答辩时若被问“这个热力图怎么算的”你打开data_processor.py指着pd.crosstab()行比解释 Matplotlib 参数直观十倍。4. 图表落地用 Plotly 渲染交互式图表并嵌入 Flask 页面静态图matplotlib答辩时会被质疑“为什么不用交互式”而商业 BI 工具Tableau/Power BI又涉及授权和安装。Plotly 是唯一满足“开源、Python 原生、前端可嵌入、导出 PNG 供论文插图”的方案。本章目标将dashboard.json中的trend和heatmap数据用 Plotly 渲染为可缩放、可悬停、可导出的图表并无缝集成到dashboard.html。重点不是炫技而是让每个图表都有明确业务含义——比如热力图的z值必须是“该类型该年份的电影数量”而非随意生成的随机数。4.1 在 Flask 路由中提供 JSON 接口解耦数据与视图虽然dashboard.json已生成但为体现“系统性”我们通过 Flask 路由提供 API 接口实际仍是读文件非实时计算# routes.py新建文件 from flask import Blueprint, jsonify import json from pathlib import Path bp Blueprint(api, __name__) bp.route(/api/dashboard-data) def get_dashboard_data(): 提供 dashboard 所需的 JSON 数据供前端 AJAX 调用 json_path Path(static/data/dashboard.json) if not json_path.exists(): return jsonify({error: 数据未生成请先运行 data_processor.py}), 500 with open(json_path, r, encodingutf-8) as f: data json.load(f) return jsonify(data)在app.py中注册蓝图# app.py 末尾追加 from routes import bp as api_bp app.register_blueprint(api_bp, url_prefix/api)此时访问http://127.0.0.1:5000/api/dashboard-data应返回 JSON 内容。这步意义重大答辩时老师说“你这图表数据哪来的”你答“通过/api/dashboard-data接口获取”立刻体现 RESTful 设计思维而非“我把数据写死在 HTML 里”。4.2 用 JavaScript 渲染趋势折线图处理空数据与异常值修改templates/dashboard.html的script区域添加趋势图渲染逻辑!-- templates/dashboard.html 中 script 标签内追加 -- script // 加载趋势图 fetch(/api/dashboard-data) .then(response response.json()) .then(data { // 趋势图配置 const trendTrace { x: data.trend.x, y: data.trend.y, type: scatter, mode: linesmarkers, name: 平均投票数, line: { color: #28a745, width: 3 }, marker: { size: 8, color: #28a745 } }; const trendLayout { title: data.trend.title, xaxis: { title: data.trend.x_label, tickangle: -45 }, yaxis: { title: data.trend.y_label }, margin: { t: 40, b: 80, l: 60, r: 20 }, hovermode: closest }; Plotly.newPlot(boxoffice-trend, [trendTrace], trendLayout); }) .catch(error { console.error(❌ 趋势图加载失败:, error); document.getElementById(boxoffice-trend).innerHTML div classalert alert-danger图表数据加载失败请检查 data_processor.py 是否已运行/div; }); /script关键细节说明fetch()异步请求避免阻塞页面hovermode: closest实现悬停显示坐标值这是交互式图表的核心体验tickangle: -45解决年份文字重叠.catch()提供降级提示防止数据缺失时页面空白——毕设演示最怕黑屏宁可显示错误提示也不留白。4.3 渲染热力图用 Plotly Heatmap 实现类型-年份矩阵热力图需注意Plotly 的z数组是[[row1], [row2]]而pd.crosstab()输出的values正是此格式可直接使用。但需反转 Y 轴顺序因 pandas 默认年份升序热力图 Y 轴从上到下应为升序!-- templates/dashboard.html 中继续追加 -- script // 热力图渲染接在趋势图之后 fetch(/api/dashboard-data) .then(response response.json()) .then(data { // 热力图配置z 需为二维数组x/y 为一维数组 const heatmapTrace { x: data.heatmap.x, y: data.heatmap.y.slice().reverse(), // 反转年份顺序使 1994 在顶部 z: data.heatmap.z.map(row [...row].reverse()), // 同步反转 z 行 type: heatmap, colorscale: Viridis, showscale: true, name: 热度 }; const heatmapLayout { title: data.heatmap.title, xaxis: { title: data.heatmap.x_label, tickangle: -45 }, yaxis: { title: data.heatmap.y_label, autorange: reversed }, // 关键强制反转 Y 轴 margin: { t: 40, b: 80, l: 100, r: 20 }, hovertemplate: 类型: %{x}br年份: %{y}br数量: %{z}extra/extra }; Plotly.newPlot(genre-heatmap, [heatmapTrace], heatmapLayout); }) .catch(error { console.error(❌ 热力图加载失败:, error); document.getElementById(genre-heatmap).innerHTML div classalert alert-danger热力图数据加载失败/div; }); /script为什么yaxis: { autorange: reversed }比手动slice().reverse()更可靠因为autorange: reversed是 Plotly 原生属性自动处理坐标轴标签、刻度、交互逻辑而手动反转z数组易出错如忘记同步反转且悬停提示y值会与实际坐标不符。这是血泪经验宁可查 10 分钟文档不自己造轮子反转数组。5. 避坑指南毕业设计中电影数据可视化系统最常见的 4 个翻车现场做毕设最怕的不是不会写代码而是花两周调通图表答辩前一晚发现数据源失效、环境崩了、或者图表逻辑被导师一句“这个相关性没解释清楚”直接推翻。以下是我在指导 42 个毕设中高频出现、且极易被忽略的 4 个坑按“现象 → 原因 → 解决”给出可立即执行的对策5.1 现象本地运行正常答辩时 U 盘拷到导师电脑上flask run报ModuleNotFoundError: No module named plotly原因未导出依赖清单导师电脑未安装plotly或版本不匹配如你用plotly5.18.0导师装了6.0.0导致 API 变更。解决项目根目录执行pip freeze requirements.txt生成精确依赖答辩前在导师电脑上执行pip install -r requirements.txt务必提前测试更稳妥做法将venv文件夹整个压缩Windows 下约 80MBU 盘携带解压后直接venv\Scripts\activate.bat激活绝对环境一致。5.2 现象热力图显示“类型: Drama, 年份: 1994, 数量: 0”但数据里明明有 1994 年的《肖申克的救赎》原因pd.crosstab()默认对缺失值NaN静默丢弃而你的genre_list列因清洗不彻底仍含空字符串或空格 被当作文本参与分组导致有效类型被稀释。解决在clean_genres_column()函数末尾增加过滤df_exploded df_exploded[df_exploded[genre_list] ! ] # 去除空字符串 df_exploded df_exploded[df_exploded[genre_list].str.len() 0] # 去除纯空格运行data_processor.py后用print(df_exploded[genre_list].value_counts().head())检查前几行是否为真实类型如Drama,Action而非或?。5.3 现象折线图 X 轴年份显示为1994.0,1995.0小数点极其突兀原因pandas.groupby().agg()返回的year列是float64类型因含 NaN转tolist()后变成1994.0。解决在generate_dashboard_data()中对yearly_stats[year]强制转整数再转字符串x: yearly_stats[year].fillna(0).astype(int).astype(str).tolist(),或更优雅yearly_stats[year] yearly_stats[year].astype(Int64)Nullable Integer再.astype(str)自动处理 NaN 为NaN前端用 JS 过滤掉。5.4 现象答辩演示时点击“数据分析”页面空白浏览器控制台报Failed to load resource: the server responded with a status of 404 (NOT FOUND)指向/api/dashboard-data原因data_processor.py未运行static/data/dashboard.json文件不存在而 Flask 路由未做存在性校验直接open()报错 500但前端 fetch 未捕获 500 状态码。解决在routes.py的get_dashboard_data()中增加文件存在性检查并返回友好错误bp.route(/api/dashboard-data) def get_dashboard_data(): json_path Path(static/data/dashboard.json) if not json_path.exists(): return jsonify({ error: 数据文件缺失, hint: 请先运行 python data_processor.py 生成数据 }), 404 # 返回 404 而非 500前端可区分处理前端fetch().catch()中判断response.status 404并显示具体提示而非笼统“加载失败”。提示以上 4 个坑100% 出现在至少 1/3 的毕设中。建议你在README.md里单独建一节《答辩前必检清单》把这 4 条写进去打印出来答辩前逐条打钩。6. 让系统真正“毕业”导出静态图插入论文 一键打包演示包毕设最终交付物不仅是能跑的代码更是 Word 论文和答辩 PPT。而论文里的图表必须是静态图片非网页截图PPT 演示需脱离开发环境。本章教你两个硬核技巧用kaleido无头导出高清 PNG 图表以及用PyInstaller打包成单个.exe文件双击即开系统。这两个动作做完你的系统才算真正“毕业”。6.1 用 kaleido 导出论文级静态图表告别截图糊图Matplotlib 导出的 PNG 常因 DPI 不足被导师批“模糊”而 Plotly 官方推荐kaleido基于 Chromium 的无头渲染器导出矢量级 PNG/SVG。安装后只需 3 行代码# export_charts.py新建文件 import plotly.graph_objects as go import json from pathlib import Path def export_static_charts(): # 读取 dashboard.json with open(static/data/dashboard.json, r, encodingutf-8) as f: data json.load(f) # 导出趋势图 trend_fig go.Figure() trend_fig.add_trace(go.Scatter( xdata[trend][x], ydata[trend][y], modelinesmarkers, linedict(color#28a745, width3), markerdict(size8, color#28a745) )) trend_fig.update_layout( titledata[trend][title], xaxis_titledata[trend][x_label], yaxis_titledata[trend][y_label], width1000, height600, fontdict(size14) ) trend_fig.write_image(docs/trend_chart.png, scale2) # scale2 提升 DPI # 导出热力图同理 heatmap_fig go.Figure(datago.Heatmap( zdata[heatmap][z], xdata[heatmap][x], ydata[heatmap][y], colorscaleViridis )) heatmap_fig.update_layout( titledata[heatmap][title], xaxis_titledata[heatmap][x_label], yaxis_title p a hrefhttps://download.csdn.net/download/No_Name_Cao_Ni_Mei/88469542 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p