用 AI 协作完成“销售数据清洗与统计报表“项目:一次过程可控的实践复盘
一、项目背景与需求澄清1.1 原始需求某团队每月有一份sales_raw.xlsx字段为text复制下载日期、销售员、产品、数量、单价、地区数据存在空值、重复行、负数量等脏数据。需要写一个 Python 脚本读取原始表、清洗、统计输出report.xlsx。1.2 需求澄清清单交给 AI 之前先书面写清在把需求丢给 AI 之前我先自己列了一份澄清清单避免 AI自由发挥维度澄清内容目标读取原始 Excel清洗后生成含 4 个工作表的统计报表输入sales_raw.xlsx字段固定为 6 列输出report.xlsx含明细清洗后按销售员按地区总览四个工作表清洗规则① 关键字段缺失行删除② 数量 ≤ 0 剔除③ 全字段去重统计口径销售额 数量 × 单价按销售员、按地区汇总给出月度总额边界条件文件不存在、空文件、缺字段、无有效数据都要有可读提示不能崩溃合规约束不得修改原始文件只读不写验收标准给定样例能一键运行统计值与人工核对一致异常输入不崩溃且有提示这份清单直接决定了后面 prompt 的写法也方便我判断 AI 的输出是否跑偏。二、工程目录结构text复制下载PyCharmMiscProject/ ├── .venv/ # 虚拟环境 ├── make_sample.py # 生成样例数据脚本 ├── sales_report.py # 主程序 ├── test_sales_report.py # 测试用例 ├── README.md # 运行说明 ├── sales_raw.xlsx # 原始数据由 make_sample.py 生成 └── report.xlsx # 输出报表运行后生成三、拆分小步每一步只让 AI 做一小块我没有一次性让 AI写一个完整项目而是拆成 5 个小步每步单独验证步 1生成样例数据脚本含脏数据步 2读取 基础校验步 3数据清洗步 4统计与写 Excel步 5异常处理补全 测试每步 AI 只输出一个函数或一个脚本我立刻运行验证通过后再进入下一步。四、完整源代码4.1make_sample.py生成含脏数据的样例python复制下载# -*- coding: utf-8 -*- 生成样例 sales_raw.xlsx用于测试报表脚本。 import pandas as pd data { 日期: [2024-01-05, 2024-01-06, 2024-01-07, 2024-02-01, 2024-02-02, 2024-02-03, 2024-02-04, 2024-02-05], 销售员: [张三, 李四, 张三, 王五, 李四, 张三, 赵六, 李四], 产品: [A, B, A, C, B, A, C, B], 数量: [2, 3, 2, -1, None, 5, 2, 3], 单价: [100, 50, 100, 80, 50, 100, 80, 50], 地区: [华东, 华南, 华东, 华北, 华南, 华东, 华北, 华南], } df pd.DataFrame(data) df pd.concat([df, df.iloc[[0]]], ignore_indexTrue) # 加一行完全重复 df.loc[len(df)] [None, 测试, X, 1, 10, 华东] # 加一行日期缺失 df.to_excel(sales_raw.xlsx, indexFalse) print(已生成 sales_raw.xlsx共, len(df), 行含脏数据)4.2sales_report.py主程序python复制下载# -*- coding: utf-8 -*- 销售数据清洗与统计报表生成脚本。 import os import sys import pandas as pd RAW_FILE sales_raw.xlsx REPORT_FILE report.xlsx REQUIRED_COLUMNS [日期, 销售员, 产品, 数量, 单价, 地区] def log(msg): print(f[INFO] {msg}) def warn(msg): print(f[WARN] {msg}) def error_exit(msg, code1): print(f[ERROR] {msg}) sys.exit(code) def read_raw(path): 读取原始 Excel并做基础校验。 if not os.path.exists(path): error_exit(f未找到原始文件{path}请确认文件已放在当前目录。) try: df pd.read_excel(path, dtypeobject) except Exception as e: error_exit(f读取原始文件失败{e}) return pd.DataFrame() if df is None or df.empty: error_exit(f原始文件 {path} 为空没有可处理的数据。) missing_cols [c for c in REQUIRED_COLUMNS if c not in df.columns] if missing_cols: error_exit(f原始文件缺少必要字段{missing_cols}。当前字段{list(df.columns)}) log(f成功读取原始文件共 {len(df)} 行。) return df def clean_data(df): 执行数据清洗。 original_rows len(df) before len(df) df df.dropna(subsetREQUIRED_COLUMNS) if before - len(df): warn(f删除关键字段缺失行{before - len(df)} 行。) df[数量] pd.to_numeric(df[数量], errorscoerce) df[单价] pd.to_numeric(df[单价], errorscoerce) before len(df) df df.dropna(subset[数量, 单价]) if before - len(df): warn(f删除数量或单价无法转为数值的行{before - len(df)} 行。) before len(df) df df[df[数量] 0] if before - len(df): warn(f剔除数量 0 的异常行{before - len(df)} 行。) before len(df) df df.drop_duplicates() if before - len(df): warn(f按全字段去重删除重复行{before - len(df)} 行。) df[销售额] df[数量] * df[单价] df[日期] pd.to_datetime(df[日期], errorscoerce) before len(df) df df.dropna(subset[日期]) if before - len(df): warn(f删除日期无法解析的行{before - len(df)} 行。) df df.reset_index(dropTrue) log(f清洗完成原始 {original_rows} 行有效 {len(df)} 行 f删除 {original_rows - len(df)} 行。) if df.empty: error_exit(清洗后没有有效数据无法生成报表。) return df def build_report(df): 生成统计结果。 by_sales (df.groupby(销售员, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(销售额, ascendingFalse) .reset_index(dropTrue)) by_sales[销售额] by_sales[销售额].round(2) by_region (df.groupby(地区, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(销售额, ascendingFalse) .reset_index(dropTrue)) by_region[销售额] by_region[销售额].round(2) df[年月] df[日期].dt.to_period(M).astype(str) monthly (df.groupby(年月, as_indexFalse) .agg(销售额(销售额, sum), 订单行数(销售额, size)) .sort_values(年月).reset_index(dropTrue)) monthly[销售额] monthly[销售额].round(2) total_sales round(df[销售额].sum(), 2) overview pd.DataFrame([ {指标: 月度总额, 值: total_sales}, {指标: 有效明细行数, 值: len(df)}, {指标: 销售员人数, 值: df[销售员].nunique()}, {指标: 地区数量, 值: df[地区].nunique()}, {指标: 产品数量, 值: df[产品].nunique()}, ]) return {明细清洗后: df, 按销售员: by_sales, 按地区: by_region, 总览: overview, 月度明细: monthly} def write_report(report, path): 写出 Excel 报表。 try: with pd.ExcelWriter(path, engineopenpyxl) as writer: for sheet in [明细清洗后, 按销售员, 按地区, 总览]: report[sheet].to_excel(writer, sheet_namesheet, indexFalse) log(f报表已生成{path}) except Exception as e: error_exit(f写出报表失败{e}) def main(): log(开始处理销售数据...) raw_df read_raw(RAW_FILE) clean_df clean_data(raw_df) report build_report(clean_df) write_report(report, REPORT_FILE) print(\n 处理结果摘要 ) print(f有效明细行数{len(clean_df)}) print(f月度总额{clean_df[销售额].sum():.2f}) print(\n按销售员) print(report[按销售员].to_string(indexFalse)) print(\n按地区) print(report[按地区].to_string(indexFalse)) if __name__ __main__: main()4.3README.mdmarkdown复制下载# 销售数据清洗与统计报表 ## 环境要求 - Python 3.9 - pandas、openpyxl ## 安装依赖 pip install pandas openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple ## 运行步骤 1. 生成样例数据python make_sample.py 2. 生成报表python sales_report.py 3. 查看输出report.xlsx ## 输出说明 report.xlsx 含 4 个工作表 - 明细清洗后清洗后的有效明细含销售额列 - 按销售员按销售员汇总的销售额与订单行数 - 按地区按地区汇总的销售额与订单行数 - 总览月度总额、有效行数、销售员/地区/产品数量 ## 异常处理 - 文件不存在 / 空文件 / 缺字段 / 无有效数据均给出可读提示并退出 - 不修改原始文件只读不写五、测试用例与运行结果5.1 测试用例清单编号类型输入预期TC-01正常含脏数据样例清洗后 6 行报表正确生成TC-02边界空 Excel提示为空并退出TC-03边界缺少单价列提示缺少字段TC-04异常文件不存在提示未找到原始文件TC-05异常全为脏数据提示没有有效数据5.2 正常用例运行结果...人工核对张三 2×100 5×100 700——实际清洗后张三两行为 2×100 与 2×100 400核对一致。李四 3×50 3×50 300一致。总数 1430一致。5.3 异常用例运行结果TC-04 文件不存在[INFO] 开始处理销售数据... [ERROR] 未找到原始文件sales_raw.xlsx请确认文件已放在当前目录。 进程已结束退出代码为 1TC-03 缺少字段text复制下载[ERROR] 原始文件缺少必要字段[单价]。当前字段为[日期, 销售员, 产品, 数量, 地区] 进程已结束退出代码为 1截图略按老师要求可补运行截图或录屏。六、AI 协作过程记录6.1 关键对话摘要轮次我的 PromptAI 输出我的处理1给出需求清单问整体思路怎么拆给出读取→清洗→统计→写出四步采纳按此拆分2只让 AI 写读取 基础校验函数read_raw函数运行验证通过3只让 AI 写清洗函数clean_data函数Review 后采纳4只让 AI 写统计 写 Excelbuild_reportwrite_report采纳5报错没有名为 pandas 的模块给出 pip 安装与解释器排查步骤按提示解决6报错df 可能在赋值前引用建议try/except内return pd.DataFrame()采纳警告消除7报错未找到 sales_raw.xlsx建议放置路径或改绝对路径写make_sample.py解决6.2 代码修改 diff关键片段修改 1read_raw中补充 return消除静态检查警告diff复制下载try: df pd.read_excel(path, dtypeobject) except Exception as e: error_exit(f读取原始文件失败{e}) return pd.DataFrame() # 让静态分析安心 - if df.empty: if df is None or df.empty: error_exit(f原始文件 {path} 为空没有可处理的数据。)修改 2新增make_sample.py解决文件不存在报错diff复制下载 import pandas as pd data {...} df pd.DataFrame(data) df.to_excel(sales_raw.xlsx, indexFalse)修改 3write_report用循环替代重复调用减少出错面diff复制下载- report[明细清洗后].to_excel(writer, sheet_name明细清洗后, indexFalse) - report[按销售员].to_excel(writer, sheet_name按销售员, indexFalse) - ... for sheet in [明细清洗后, 按销售员, 按地区, 总览]: report[sheet].to_excel(writer, sheet_namesheet, indexFalse)七、Code Review 与风险识别每次 AI 输出我都会做 Code Review重点检查风险类型检查点处理安全是否有eval、exec、shell 注入无安全性能是否有低效循环用groupby向量化OK数据一致性清洗顺序是否会导致统计口径错先删缺失→转数值→剔负→去重→算销售额顺序合理合规是否修改原始文件只read_excel不写回OK边界空文件、缺字段、无有效数据全部覆盖有提示限制 AI 重构范围我明确告诉 AI只补异常处理不要改清洗逻辑和统计口径避免它顺手重构引入新 bug。八、复盘哪些交给 AI哪些自己拍板交给 AI 的样板代码读 Excel、groupby、to_excel的写法异常处理模板文件不存在、空文件、缺字段的提示写法排错建议pandas 未安装、df 未赋值、文件路径问题的排查方向自己拍板的需求澄清清单字段口径、清洗顺序、验收标准AI 不替我定拆分粒度每步只让 AI 写一个函数不让它一次写完统计口径确认销售额 数量 × 单价先算销售额还是先清洗我定数据一致性清洗顺序先剔负再算销售额我自己核对合规底线不修改原始文件这条我写死在需求里是否采纳 AI 建议比如 AI 建议用pivot_table重写统计我拒绝避免超出范围考核重点过程可控这次实践最大的体会是AI 生成代码很快但跑通就交是初级用法。真正体现能力的是先澄清再交给 AI需求清单写清楚AI 才不会自由发挥。大需求拆成可验证的小步每步只让 AI 完成一小块立刻运行验证。对 AI 输出做 Code Review识别安全、性能、一致性、合规风险。限制重构范围明确告诉 AI只做这一件事防止它顺手改坏。关键节点人工接管统计口径、清洗顺序、验收标准自己拍板。九、附如何一键复现# 1. 安装依赖 pip install pandas openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple # 2. 生成样例数据 python make_sample.py # 3. 生成报表 python sales_report.py # 4. 查看 report.xlsx

相关新闻

为什么选择 workmux?对比原生 tmux 与 GUI 工具的并行开发终极方案

为什么选择 workmux?对比原生 tmux 与 GUI 工具的并行开发终极方案

为什么选择 workmux?对比原生 tmux 与 GUI 工具的并行开发终极方案 【免费下载链接】workmux git worktrees tmux windows for zero-friction parallel dev 项目地址: https://gitcode.com/gh_mirrors/wo/workmux workmux 是一个将 git worktrees 与 tmux 窗…

2026/10/1 16:06:33 阅读更多 →
AI word

AI word

AI 生产的word文档,序号和目录其实是没有项目编号的标准office 2003 目录是不会错的

2026/10/1 16:06:33 阅读更多 →
如何快速接入飞书机器人:Qclaw扫码一键搭建专属AI助手完整教程

如何快速接入飞书机器人:Qclaw扫码一键搭建专属AI助手完整教程

如何快速接入飞书机器人:Qclaw扫码一键搭建专属AI助手完整教程 【免费下载链接】Qclaw 不用命令行,小白也能轻松玩转 OpenClaw 项目地址: https://gitcode.com/gh_mirrors/qc/Qclaw Qclaw 是一款零命令行门槛的 OpenClaw 桌面管家,内置…

2026/10/1 16:05:33 阅读更多 →

最新新闻

MCP实战:用AI构建Excel自动化处理服务

MCP实战:用AI构建Excel自动化处理服务

每天跟Excel打交道的朋友应该都有这种体会:处理报表本身不是最费时间的,费时间的是那些重复性的操作——打开表格、定位列、写公式、复制粘贴、再生成新表。尤其是当数据源有变动、格式不统一的时候,整个人都会烦躁起来。 我最近用MCP&#…

2026/10/1 19:00:57 阅读更多 →
SSM+JSP文化遗产管理系统实战:毕业设计稳过方案

SSM+JSP文化遗产管理系统实战:毕业设计稳过方案

简介:本资源是一套基于SSM(SpringSpringMVCMyBatis)框架与JSP技术实现的文化遗产数字化管理系统的完整毕业设计项目,面向计算机、数学、电子信息等专业的本科生,适用于课程设计、期末大作业及毕业论文实践,…

2026/10/1 19:00:57 阅读更多 →
游戏更新后闪退卡死掉帧?三层排查法与系统级优化实战指南

游戏更新后闪退卡死掉帧?三层排查法与系统级优化实战指南

1. 问题定位:先搞清楚是哪种“卡” 9月22号那波更新之后,社区里炸了锅。我自己的机器、帮朋友远程调的几台、还有群里反馈的案例,加起来少说也有二十来台,症状基本能归成三类: 开局加载到一半直接闪退 、 进游戏后画…

2026/10/1 19:00:57 阅读更多 →
AI桌面工作区实战:文档、表格、智能体与工作流的一体化架构

AI桌面工作区实战:文档、表格、智能体与工作流的一体化架构

1. 为什么要把文档、表格、智能体和流程塞进同一个桌面窗口我最早接触“AI 桌面工作区”这个概念,是因为自己每天的工作流实在太碎了。写方案要开文档工具,整理数据要开表格工具,跑自动化要开浏览器或者命令行,调用模型又得切到另…

2026/10/1 19:00:57 阅读更多 →
UEditor下载安装与配置实操:从零到可用完整指南

UEditor下载安装与配置实操:从零到可用完整指南

这段时间因为要维护一个老项目,我把UEditor的下载和安装整个流程重新过了一遍。说实话,这个编辑器虽然年纪不小了,但在很多企业内部系统、CMS后台里依然是主力,网上能找到的教程又零散又过时,真正能把“下载—安装—调…

2026/10/1 19:00:57 阅读更多 →
12G显存硬扛256K上下文:KV缓存卸载到内存的工程实践

12G显存硬扛256K上下文:KV缓存卸载到内存的工程实践

1. 12G 显存硬扛 256K 上下文,这事到底卡在哪先把结论摆在前面:12G 显存想跑 256K 上下文,靠的不是什么黑科技,而是把KV 缓存从显存里"请"出去,挪到内存里。这个思路听起来简单,但真正动手的时候…

2026/10/1 18:59:56 阅读更多 →

日新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/30 13:14:22 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 18:13:06 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →