数学建模国赛备赛:模块化数据处理与论文图表绘制技能包
2026/9/7 5:26:10 网站建设 项目流程

2026年数学建模国赛备赛期已经可以开始了。不管是第一次参赛还是拿过奖的老队伍,竞赛里最耗时的永远不是模型推导本身,而是问题分析、数据处理、图表绘制这三个环节来回返工。很多队伍两天下来,真正用于建模和论文的时间不到三分之一,剩下的时间都耗在数据清洗、变量定义不清、图表改了一遍又一遍上。这次我们把这套流程整理成模块化求解 skill,让每个环节都有标准流程、可复用脚本和验收清单。

这里说的 skill,不是简单的一句提示词,而是一套由说明文件、Python 脚本、检查清单组成的技能包。拿到赛题后,先跑问题分析 skill 完成题目拆解,再通过数据处理 skill 把原始数据清洗成标准化表格,最后由图表绘制 skill 直接产出论文级图表。整个过程人可以介入,AI 也可以按同一套流程执行,既适合备赛阶段训练,也适合比赛现场快速出结果。下面直接给核心能力和落地步骤。

1. 核心能力速览

能力项说明
解决目标将数模国赛中的问题分析、数据处理、图表绘制三个环节标准化、模块化
模块划分问题分析 skill、数据处理 skill、图表绘制 skill
输出产物赛题拆解文档、标准化数据表格、论文级图表、批量处理结果
运行环境Python 3.8 及以上,依赖 pandas、numpy、matplotlib、seaborn、openpyxl
是否需要 GPU不需要,这套 skill 以数据处理为主,CPU 即可运行
启动方式命令行逐模块执行,或封装为 HTTP API 服务
是否支持批量任务支持,通过批量脚本遍历输入目录自动处理
是否支持接口 API支持,可封装为 FastAPI 服务供团队共享
适用对象数模国赛参赛队伍、建模实验课程、需要快速出图出表的科研团队
扩展方向接入 AI 助手后,可让 AI 按同一套 SOP 自动执行各模块

从功能上看,这套方案不依赖昂贵的硬件,也不依赖某个特定的在线平台,所有脚本都可以在本地测试通过后直接用于比赛场景。核心价值是把“凭感觉做”变成“按流程做”,把重复劳动压缩到最小。

2. 适用场景与使用边界

这套 skill 最适合下面几类人:

  • 第一次参加数模国赛的队伍。队伍里如果有人熟悉 Python,按照本文的脚本和 SOP 把三个模块跑通,比赛时就不用手忙脚乱。
  • 已经参赛过但总在数据环节返工的队伍。数据清洗和图表绘制统一成脚本后,换一套数据也能快速产出结果。
  • 需要批量复现实验结果的场景。比如需要同时处理多份实验数据、多组调查问卷、多张表格,手动操作容易出错,脚本批量处理更稳定。

它能解决的问题也很明确:问题分析阶段不会拆题,拿到题目不知道先做什么;数据处理阶段反复清洗同一份数据,代码写一次丢一次;图表绘制阶段风格不统一,论文插图很难看。

但这套 skill 不能替代真正的建模能力。它负责流程标准化,不负责替你决定用哪个模型、怎么写一篇有竞争力的论文。如果队伍本身对微分方程、线性规划、统计分析这些基础模型不熟悉,先补数学基础,再谈 skill 提效。另外,竞赛对 AI 辅助参赛通常有明确规则,使用任何自动化工具或 AI 生成内容前,务必阅读当年赛区发布的参赛规则,按要求完成必要的声明和合规操作。

数据使用也有边界。清洗和绘图的数据必须来自合法渠道,涉及个人信息的要先脱敏,涉及企业或单位数据要确认授权。图表导出后如果用于论文或公开发布,需要确保数据来源和引用说明完整。

3. 环境准备与项目目录规划

3.1 本地环境检查

这套 skill 只需要一个相对干净的 Python 环境。推荐使用 3.8 及以上版本,安装依赖时用虚拟环境隔离,避免和系统 Python 冲突。如果你的机器上已经装了 Anaconda,可以直接创建一个独立环境:

# 创建并激活虚拟环境,命令在 Windows、Linux、macOS 上通用 python -m venv skill_env source skill_env/bin/activate # Windows 使用 skill_env\Scripts\activate

然后安装基础依赖:

pip install pandas numpy matplotlib seaborn openpyxl

pandas 负责表格读取与清洗,numpy 负责数值计算,matplotlib 和 seaborn 负责图表绘制,openpyxl 用来读写 Excel 文件。如果后面要封装 HTTP API,再额外安装:

pip install fastapi uvicorn python-multipart

3.2 推荐目录结构

比赛环境文件多且乱,强烈建议在拿到赛题的第一时间就建立统一目录。下面是一个可以直接套用的结构:

project/ ├── data/ │ ├── inputs/ # 原始数据放这里 │ ├── outputs/ # 清洗后的数据 │ └── raw.csv # 单份数据也可以直接放在 data 下 ├── outputs/ │ └── figs/ # 图表输出目录 ├── skills/ │ ├── problem_analysis/ # 问题分析 skill │ ├── data_process/ # 数据处理 skill │ └── plot/ # 图表绘制 skill ├── scripts/ │ ├── data_clean.py │ ├── plot_charts.py │ └── batch_run.py └── README.md

把原始数据、清洗数据、图表输出分开存放,最大的好处是比赛最后写论文时能快速找到素材,不会出现“图在哪、数据是哪一版”的混乱。每一份数据修改后另存为新文件,不要覆盖原始文件。

4. skill 模块设计与配置文件

skill 模块化设计的核心是一份说明文件加若干可执行脚本。说明文件让 AI 或队友理解这个模块是做什么的、输入输出是什么、验收标准是什么;脚本负责把流程跑起来。下面给出一个通用 skill 配置模板,路径和参数需要按实际项目调整。

4.1 skill 文件结构

skills/ ├── problem_analysis/ │ ├── SKILL.md │ └── analysis_template.md ├── data_process/ │ ├── SKILL.md │ └── data_clean.py └── plot/ ├── SKILL.md └── plot_charts.py

4.2 以数据处理 skill 为例的 SKILL.md

# 数模国赛-数据处理Skill ## 功能定位 将竞赛中的原始数据清洗、转换、特征工程标准化,输出可直接用于建模的表格。 ## 输入 - 原始数据文件(CSV / Excel) - 数据说明文档(可选) ## 处理流程 1. 加载数据并检查字段类型 2. 处理缺失值:数值列用均值或中位数填充,类别列用众数填充 3. 去重、去全空列 4. 异常值检测:使用 3σ 原则或 IQR 方法 5. 输出标准化编码数据 ## 调用方式 bash python scripts/data_clean.py --input data/raw.csv --output data/processed.csv ## 验收标准 - 无全空列、无重复行 - 数值列无字符串混入 - 输出文件编码为 UTF-8

有了这份 SKILL.md,无论是队友手动执行还是 AI 调用,都能按同一套标准完成数据处理,不会出现两个人洗出两份完全不同的表的尴尬情况。

5. 问题分析 skill:赛题拆解与验收测试

5.1 为什么需要单独做一个问题分析 skill

很多队伍拿到赛题后直接把题目丢给 AI,让 AI 给一个模型就开写。这样做的结果是论文读起来“没有灵魂”,题目其实没有被真正拆透。问题分析 skill 要做的是把拆题变成一个可重复、可验收的动作链:先把题目背景压缩成三句话,再列出关键变量、约束条件和需要假设的点,最后给出至少两种建模路线并对复杂度做预判。

5.2 问题分析流程模板

下面是一个可以直接复制到团队的 analysis_template.md 的模板:

# 赛题拆解模板 ## 1. 问题背景 用 3 句话概括题目场景,确保队伍所有人对题目理解一致。 ## 2. 问题重述 用自己的语言复述要解决什么问题,禁止直接抄题目原文。 ## 3. 变量定义表 | 变量名 | 含义 | 类型 | 单位 | | --- | --- | --- | --- | ## 4. 约束条件 - 硬约束:题目中不可违反的条件 - 软约束:可以通过目标函数权衡的条件 ## 5. 假设清单 每个假设都写明对结果的影响,方便后期在论文中说明局限性。 ## 6. 建模路线对比 | 路线 | 模型 | 输入 | 输出 | 复杂度 | 风险点 | | --- | --- | --- | --- | --- | --- |

5.3 验证问题分析是否达标

判断问题分析 skill 是否跑通的标志很简单:队伍里任何一个人不看题目原文,只看拆解文档,也能复述出这道题要做什么、数据从哪里来、输出结果应该是什么样。如果拆解文档里变量表是空的、约束条件只有一条、假设清单混乱,说明还没有完成。

建议在拿到赛题后 2 到 3 小时内完成问题分析,不要在这个阶段纠结具体模型公式。拆题越清楚,后面的数据清洗和建模越顺利。这个阶段产出的变量定义表要保留到论文写作阶段,避免前后不一致。

6. 数据处理 skill:清洗脚本与效果验证

6.1 功能说明

数据处理 skill 是整个流程里最容易标准化、也最容易出问题的一环。竞赛中拿到的数据普遍存在列名不规范、单位混用、缺失值、重复记录、文本数字混在一起等问题。下面提供一个通用清洗脚本,它会把 CSV 或 Excel 读进来,去掉全空行和全空列,去重,然后把数值类型的文本列自动转成数字。

# scripts/data_clean.py # 通用数据清洗脚本:读取原始数据,输出标准化表格 import pandas as pd from pathlib import Path def load_data(path: str) -> pd.DataFrame: path = Path(path) if path.suffix == ".csv": return pd.read_csv(path, encoding="utf-8-sig") if path.suffix in (".xlsx", ".xls"): return pd.read_excel(path) raise ValueError(f"不支持的文件格式: {path.suffix}") def clean(df: pd.DataFrame, drop_duplicates: bool = True) -> pd.DataFrame: # 去除全空列和全空行 df = df.dropna(axis=1, how="all").dropna(axis=0, how="all") if drop_duplicates: df = df.drop_duplicates() # 数值列统一转为 float,非数值列保留为对象 for col in df.columns: if df[col].dtype == object: numeric = pd.to_numeric(df[col], errors="coerce") if numeric.notna().sum() >= 0.8 * df[col].notna().sum(): df[col] = numeric return df def fill_missing(df: pd.DataFrame) -> pd.DataFrame: for col in df.columns: if df[col].dtype in ("float64", "int64", "float32", "int32"): df[col] = df[col].fillna(df[col].median()) else: df[col] = df[col].fillna(df[col].mode()[0] if not df[col].mode().empty else "未知") return df if __name__ == "__main__": df = load_data("data/raw.csv") df_clean = fill_missing(clean(df)) df_clean.to_csv("data/processed.csv", index=False, encoding="utf-8-sig") print(f"清洗完成:共 {len(df_clean)} 行,{len(df_clean.columns)} 列")

这个脚本不是银弹。业务含义明显的数据不能盲目填充中位数,比如某列是“是否发生故障”,0 和 1 的缺失值用中位数填充就没有意义。使用时要根据题目说明文档判断每个字段应该怎么处理。

6.2 效果验证方法

假设你有一份 data/raw.csv,里面混了空行、重复行和字符串形式的数字,运行:

python scripts/data_clean.py

如果输出:

清洗完成:共 120 行,5 列

并且用 pandas 重新读取 processed.csv 后没有报类型错误,说明清洗通过。更严格的验证方式是打印每一列的数据类型和缺失值比例:

import pandas as pd df = pd.read_csv("data/processed.csv", encoding="utf-8-sig") print(df.info()) print(df.isna().sum())

正常情况下 processed.csv 应该没有全空列,数值列的类型是 float64 或 int64,缺失值数量为 0。如果输出仍有缺失值,说明 fill_missing 阶段没有覆盖所有列,需要回去检查填充逻辑。

6.3 常见失败场景

清洗脚本最常见的问题是编码。很多比赛数据会用 GBK 编码保存,直接用 utf-8-sig 读取会报 UnicodeDecodeError。这时可以把读取参数改成:

pd.read_csv(path, encoding="gbk")

或者使用 pandas 的自动编码识别,在读取前用 chardet 检测文件编码。另一个问题是数字列里混着“暂无”“-”这类占位符,to_numeric 会把这些转成 NaN,后续填充逻辑要能容忍这种情况。

7. 图表绘制 skill:论文级图表与验证

7.1 论文图表的基本要求

数模论文里的图表不只是展示结果,更是论文评审的重要依据。图表绘制 skill 要解决两个问题:一是风格统一,二是输出尺寸满足论文排版需求。一套统一风格包含:同一字体、同一种配色、统一分辨率、坐标轴标签完整。下面给出一个通用绘图配置脚本,包含折线图和相关性热力图两个最常用的图表类型。

# scripts/plot_charts.py # 配置化图表绘制:每个图表由一组配置驱动 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False def plot_line(df: pd.DataFrame, x: str, y: list, output: str = "line.png"): fig, ax = plt.subplots(figsize=(10, 5)) for col in y: ax.plot(df[x], df[col], label=col, marker="o") ax.set_xlabel(x) ax.set_ylabel("数值") ax.set_title(f"{x} 与 {', '.join(y)} 的关系") ax.legend() ax.grid(True, alpha=0.3) fig.tight_layout() fig.savefig(output, dpi=150) plt.close(fig) def plot_corr(df: pd.DataFrame, output: str = "corr.png"): numeric = df.select_dtypes(include="number") fig, ax = plt.subplots(figsize=(8, 6)) if len(numeric.columns) > 1: sns.heatmap(numeric.corr(), annot=True, cmap="coolwarm", ax=ax) fig.tight_layout() fig.savefig(output, dpi=150) plt.close(fig) if __name__ == "__main__": data = pd.read_csv("data/processed.csv", encoding="utf-8-sig") numeric_cols = data.select_dtypes(include="number").columns.tolist() if len(numeric_cols) >= 1: plot_line(data, data.columns[0], numeric_cols[:3], "outputs/figs/line.png") if len(numeric_cols) >= 2: plot_corr(data, "outputs/figs/corr.png") print("图表绘制完成,结果输出到 outputs/figs 目录")

7.2 图表绘制测试

运行:

python scripts/plot_charts.py

然后检查 outputs/figs 目录是否生成 line.png 和 corr.png。打开图片,重点看三处:中文字体是否乱码、坐标轴标签是否完整、图例是否遮挡数据。中文字体问题最常见,如果系统上没有 SimHei,可以换成“Microsoft YaHei”或者系统自带的其他中文字体,或者直接把字体文件路径写进配置:

import matplotlib.font_manager as fm font = fm.FontProperties(fname="/path/to/font.ttf") plt.rcParams["font.family"] = font.get_name()

7.3 图表验收清单

判断图表是否达到论文标准,可以对照这份清单:

  • 图片分辨率是否达到 150dpi 以上;
  • 图中所有文字是否清晰可读;
  • 坐标轴是否有单位和标签;
  • 图例是否说明每个系列的含义;
  • 颜色方案是否统一(整篇论文不超过 2 到 3 个配色);
  • 图片文件名是否与论文中的图编号对应。

比赛时时间紧张,不建议临时手写绘图代码。把常用图表模板提前准备好,比赛时只改数据和标签,是最稳妥的做法。

8. 批量任务、接口 API 与运行效率

8.1 批量处理多个数据文件

竞赛中经常出现多张数据表需要相同处理流程的情况。比如题目给了 5 年的数据、每个年份一个文件,或者多个省份的观测数据,这时手工逐个跑一遍效率太低。批量脚本可以遍历输入目录,自动处理所有文件并输出对应结果。

# scripts/batch_run.py # 批量处理:遍历输入目录,逐文件执行数据清洗和图表绘制 from pathlib import Path import pandas as pd from data_clean import load_data, clean, fill_missing from plot_charts import plot_line, plot_corr def process(path: Path): print(f"开始处理:{path.name}") df = fill_missing(clean(load_data(str(path)))) out_sub = Path("outputs") / path.stem out_sub.mkdir(parents=True, exist_ok=True) df.to_csv(out_sub / "processed.csv", index=False, encoding="utf-8-sig") numeric_cols = df.select_dtypes(include="number").columns.tolist() if len(numeric_cols) >= 2: plot_corr(df, str(out_sub / "corr.png")) if len(numeric_cols) >= 1: plot_line(df, df.columns[0], numeric_cols[:3], str(out_sub / "line.png")) print(f"完成:{path.name}") if __name__ == "__main__": inputs = Path("data/inputs") for f in sorted(inputs.glob("*.csv")) + sorted(inputs.glob("*.xlsx")): process(f)

批量任务要注意两个问题。第一,单个文件处理失败不能中断整个流程,建议在 process 函数里加 try/except,失败时打印错误信息并跳过。第二,输出目录要按文件名区分,避免文件覆盖。上面的脚本已经把每个文件的输出放在以文件名命名的子目录里。

8.2 封装为 HTTP API 服务

如果队伍人数多,需要多人共用一套数据处理和绘图能力,可以把脚本封装成 FastAPI 服务。这样团队里不熟悉 Python 的同学也能通过网页或接口直接上传数据、获取结果。

# scripts/api_service.py # 示例:将数据清洗和绘图封装为 HTTP API,需要按实际项目调整 from fastapi import FastAPI, UploadFile import pandas as pd from data_clean import clean, fill_missing from plot_charts import plot_corr app = FastAPI() @app.post("/clean") async def clean_file(file: UploadFile): df = pd.read_csv(file.file, encoding="utf-8-sig") cleaned = fill_missing(clean(df)) return { "rows": len(cleaned), "columns": len(cleaned.columns), "missing": int(cleaned.isna().sum().sum()), "sample": cleaned.head(3).to_dict(orient="records") } @app.post("/plot") async def create_plot(file: UploadFile): df = pd.read_csv(file.file, encoding="utf-8-sig") cleaned = fill_missing(clean(df)) plot_corr(cleaned, "outputs/api_corr.png") return {"status": "ok", "output": "outputs/api_corr.png"}

启动服务:

uvicorn scripts.api_service:app --host 127.0.0.1 --port 8000

然后可以用 curl 验证接口:

curl -X POST http://127.0.0.1:8000/clean \ -F "file=@data/raw.csv"

接口返回 JSON 格式的行数、列数、缺失值数量和样例数据,说明接口已经正常工作。封装 API 时要注意只监听 127.0.0.1,不要暴露到公网,避免别人直接往你服务器上传数据。

8.3 运行效率与资源占用观察

数据处理和图表绘制的资源占用不像深度学习模型那么夸张,但也不是完全不需要关注。当数据量达到几十万行、列数有几十列时,内存占用会明显上升。观察方法有两种:一是在命令行用 time 命令统计脚本总耗时,二是用 psutil 或系统任务管理器观察内存变化。

time python scripts/data_clean.py

降低内存占用的常用手段:只读取需要的列,不要全表读入;把不用的列在清洗后立刻删除;用 pd.to_numeric 压缩数据类型;数据量过大时用分块读取:

chunks = pd.read_csv("data/large.csv", chunksize=10000) result = [] for chunk in chunks: result.append(clean(chunk)) df = pd.concat(result, ignore_index=True)

比赛期间如果遇到数据文件特别大,先处理成小文件再建模,不要一上来就全量加载。

9. 常见问题与排查方法

问题现象可能原因排查方式解决方案
读取 CSV 报 UnicodeDecodeError文件编码不是 UTF-8用记事本或 vim 查看文件编码将读取参数改为 gbk,或先用文本编辑器另存为 UTF-8
清洗后列数变少dropna(axis=1) 把部分缺失列删掉了打印删除前的列名确认全空列定义是否符合预期,必要时改为手动删除指定列
数值列变成 object 类型列中混入文本占位符打印该列取值分布先替换占位符为 NaN,再做 to_numeric 转换
中文字体显示为方块系统缺少对应字体查看 matplotlib 字体警告指定系统中文字体文件路径
图例遮挡数据图例位置不合理打开图片观察设置 loc="upper left" 或调整 figsize
批量任务一个文件报错中断没有 try/except 保护查看错误堆栈在循环内部捕获异常并跳过
接口返回 500 错误上传文件格式不支持查看服务日志检查接口是否只支持 CSV,扩展支持 Excel
文件被覆盖输出路径重复检查目录结构按输入文件名建立子目录
清洗后数据量骤减去重逻辑太激进比较去重前后行数把 drop_duplicates 限定在关键列上
比赛现场找不到输出文件目录结构混乱检查工作目录使用绝对路径并统一 outputs 目录

上面这些问题,前三个在数据处理中最常见,中文字体问题在图表绘制中最常见。建议比赛前一天把脚本在比赛环境完整跑一遍,确认没有路径或编码问题后再封箱。

10. 最佳实践与使用建议

10.1 第一天先完整跑通一条流程

拿到赛题后,先不要急着读论文或套模型。按照问题分析 skill 完成拆题,然后把题目数据跑一遍数据处理和图表绘制的默认脚本,确认输出正常。这样即使后面换模型、换思路,你手里已经有一份干净的标准化数据和一组可用的基础图表。

10.2 版本管理比想象中重要

比赛三天,代码和数据会改很多次。建议用 Git 管理项目,至少做到“当天结束前提交一次”。如果不熟悉 Git,也可以用最简单的办法:每次修改前把文件复制一份,文件名带上日期和版本号。这个习惯能避免比赛最后一天出现“改完数据处理脚本后原图消失”的情况。

10.3 把 skill 文档写进团队协作流程

SKILL.md 不只是给 AI 看的,也是给队友看的。建议队伍里负责写作的同学也读一遍数据处理和图表绘制两个 skill 的说明,这样他在写论文时知道手上的表是哪一步生成、图表是怎么画的,写出来的分析才有依据。问题分析 skill 产出的变量定义表,要一直沿用到最后论文的模型假设和符号说明章节。

10.4 合规使用工具和数据

如果要在比赛中借助 AI 工具,一定要确认竞赛规则是否允许、需要不需要申报。数据处理脚本生成的图表如果引用外部数据,要在论文中注明数据来源。涉及未公开数据的,不要擅自上传到在线平台,优先使用本地脚本处理。

10.5 下一步扩展方向

这套 skill 目前覆盖了数据竞赛中最高频的三个模块。后续可以继续扩展:把常用统计检验做成单独的 skill 模块,把论文排版规范固化到 LaTeX 模板里,把数据标准化与归一化封装成可配置参数,甚至把整套流程接入团队自己的 API 服务,参赛时所有成员统一调用。先把基础流程跑顺,再逐步叠加新模块,是最务实推进方式。建议把这套方案在模拟赛上完整跑一遍,把踩到的坑提前排掉。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询