ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Python和AI自动生成销售汇总与异常清单

用Python和AI自动生成销售汇总与异常清单 下午两点领导在群里发来一句话把上个月的销售情况整理一下按区域和产品线汇总异常项标出来下班前给我。你打开那6000多行的销售明细心里很清楚如果继续用“透视表肉眼找异常”的老办法今天大概率又要加班到九点。这类任务看起来简单真正做起来却格外耗时。原因是你在用 Excel 同时完成两件事第一件是数据聚合按区域求和、按产品分组、按时间切片规则完全确定第二件是业务判断哪块区域下滑了、哪个产品异常、哪一条线需要重点提醒。数据聚合是代码一秒能完成的事业务判断则依赖经验和上下文。大多数人的做法是把这两件事混在一起在 Excel 里来回筛选、复制、写备注最后再拼成一份汇报材料。我的判断很明确销售汇总这件事正确做法是让代码处理所有确定性操作让大模型辅助完成需要业务直觉的异常识别人只做最终确认。这不是要搭建一套昂贵的数据平台一个 Python 脚本加上大模型 API 就完全够用。接下来我会用一个完整可运行的示例演示如何把销售明细自动变成区域汇总表、产品汇总表和异常清单。文章里会涉及数据清洗、pandas 聚合、大模型提示词设计、Excel 导出和常见排错建议先收藏再实操。1. 这篇文章真正要解决的问题为什么“领导下午就要汇总”会让人焦虑因为时间紧、数据量大、要求还不低。汇总表看似简单实际包含三个环节先要搞清楚数据本身干不干净然后完成多维度汇总最后还要挑出“值得领导看”的异常点。三个环节里前两个是可以自动化的第三个才是价值核心却也最容易卡住新手。很多人会想异常不就是最高最低吗不是。真实业务中销售额最高和最低的区域也许每年都是那两个它们根本不是异常真正的异常是本周华东区域突然跌了 40%或者某个产品退货率明显偏离历史均值。这类判断需要结合数据分布、业务常识和分析经验。如果你只是把表格做出来领导问“有哪些异常”你还要现场翻数据那这个汇总的价值就少了一半。如果你把异常清单提前准备好了哪怕只有三条也证明你真正把数据看懂了。本文要解决的就是如何用一套半自动化流程让“汇总表异常清单”在半小时内产出。读完你会掌握下面的组合方法用 pandas 做确定性的分组统计把汇总结果以文本形式传给大模型让大模型基于业务规则输出结构化的异常候选再人工确认并写入 Excel。整个流程可以直接复用到月度汇总、周报、渠道分析等场景。适用读者包括经常被临时要数据的产品、运营和销售助理刚接触 Python 数据分析的开发者以及所有想用 AI 提升办公效率的职场人。你不需要有多深的机器学习基础但至少要能在本机运行 Python 脚本。2. 方案思路代码负责确定AI 负责判断先明确一个认知这个方案不是在做一个自动生成报表的“智能系统”而是把人的工作流拆成两层。第一层是规则层。按区域求和、按产品汇总、计算订单数、计算总销量这些操作结果固定、逻辑清晰。过去在 Excel 里用 SUMIF 和数据透视表完成现在改用 pandas好处是脚本可复用。数据一更新运行一次代码所有结果跟着更新。这一层最大的坑是数据清洗日期字段的类型、空值、重复行、金额单位不一致都会影响最终结果。第二层是判断层。大模型本身不能精确计算几千行数据的加总但它非常擅长“对着汇总结果做业务解读”。你把分组和汇总后的数据变成一段文本让模型按设定好的框架找出异常比如离群值、环比突变、长尾分布。这一层的作用不是替代数据分析师而是帮分析师快速圈定值得看的地方。为什么不在第一层直接写规则来识别异常比如用“超过平均值两倍算异常”这种阈值。阈值法的问题在于业务场景多变不同的产品线、不同的季节、不同的区域基础体量异常定义完全不同。写一整套可维护的规则逻辑复杂度很高。大模型的好处是你可以在提示词里描述业务背景它就能基于描述给出带理由的候选异常。这个方案的实用边界也要说清楚。如果公司已经上了 BI 系统有现成的驾驶舱和告警规则那本文方案适合作为临时补充如果只是周报月报需要跑数这个脚本就是最有性价比的方案。它不是银弹但对于个人效率提升效果是立竿见影的。3. 环境准备与前置条件在开始写代码之前先确认你本机的环境。以下是我的建议版本以实际安装为准本文重点演示通用思路。3.1 运行环境操作系统Windows、macOS、Linux 均可Python 版本3.9 及以上包管理工具pip 或 conda需要安装的 Python 库如下pip install pandas openpyxl openaipandas 用于数据处理openpyxl 用于写入 Excel 文件openai 是调用大模型 API 的官方 SDK。3.2 大模型 API本文示例使用 OpenAI 兼容接口原因有两个一是 OpenAI Python SDK 目前是事实标准几乎所有主流国产大模型都提供兼容接口二是你只需要改 base_url 和 model 名称就能切换到不同模型代码结构不用变。你需要准备一个 API Key同时确认模型支持 function calling 之外的普通 chat completion。本文用的是 chat.completions.create 接口非常常规。如果公司内部部署了模型或者你本地有 Ollama 跑开源模型也可以把 base_url 指向本地服务。具体是否支持查看你所用服务的文档即可。生产环境建议把 API Key 放在环境变量里而不是写死在代码中后面会有专门的安全说明。3.3 数据准备为了把流程跑通你需要一份销售明细数据。真实数据的字段通常包括销售日期、区域、销售员、产品、数量、单价、销售单号等。我准备了一份模拟数据生成代码方便你本地直接测试。真实场景你只需要把文件路径换成自己的 Excel 即可。# 文件路径generate_data.py import pandas as pd import numpy as np np.random.seed(42) regions [华东, 华南, 华北, 西南, 东北] products [智能手环, 蓝牙耳机, 移动电源, 智能音箱, 车载充电器] salesmen [张伟, 王芳, 李强, 赵敏, 刘洋, 陈晨, 周磊, 吴桐] rows [] for i in range(3000): region np.random.choice(regions) product np.random.choice(products) salesman np.random.choice(salesmen) date pd.Timestamp(2025-06-01) pd.Timedelta(daysint(np.random.randint(0, 30))) quantity int(np.random.randint(1, 20)) price float(np.random.randint(50, 300)) order_id fSO-{i1000:05d} rows.append([order_id, date.strftime(%Y-%m-%d), region, salesman, product, quantity, price]) df pd.DataFrame(rows, columns[销售单号, 销售日期, 区域, 销售员, 产品名称, 数量, 单价]) df.to_excel(销售明细.xlsx, indexFalse) print(模拟数据已生成销售明细.xlsx)运行这段代码后你会得到一个 3000 行的模拟 Excel 文件。后文所有代码都基于这个文件演示。4. 第一步读取明细完成数据清洗拿到真实销售明细后不要急着聚合先看数据质量。实际业务里常见的问题包括销售日期是字符串甚至有的是 Excel 序列号需要转换数量、单价列存在空值或者被错误地识别为文本同一笔订单有多行明细统计订单数时必须去重金额没有单独字段需要用数量和单价计算数据清洗的目标是让数据变成规整的 DataFrame。下面的代码做了四件事读取 Excel、转换日期类型、计算销售额、提取月份字段。# 文件路径data_loader.py import pandas as pd def load_sales_data(file_path: str) - pd.DataFrame: 读取销售明细并完成基础清洗 df pd.read_excel(file_path) # 1. 标准列名如果列名有空格或不同命名可以在这里统一 df.columns [col.strip() for col in df.columns] # 2. 日期转换为 pandas 时间类型 df[销售日期] pd.to_datetime(df[销售日期]) # 3. 数量、单价转为数值类型出错时强制转 NaN df[数量] pd.to_numeric(df[数量], errorscoerce) df[单价] pd.to_numeric(df[单价], errorscoerce) # 4. 删除关键字段为空的行 df df.dropna(subset[数量, 单价]) # 5. 计算销售额 df[销售额] df[数量] * df[单价] # 6. 提取月份方便后续按月度汇总 df[月份] df[销售日期].dt.to_period(M) return df if __name__ __main__: sales_df load_sales_data(销售明细.xlsx) print(sales_df.head()) print(sales_df.info())运行后你会看到类似输出3000 行数据字段类型正确销售额列已经生成。这里有一个值得养成的习惯把清洗逻辑封装成函数不要在主流程里写一大堆散装代码后面重新调用会方便很多。清洗这一步最容易出的问题是日期格式不统一。真实 Excel 里可能有的单元格是“2025/6/1”有的是“20250601”还有的是文本。遇到这种情况可以先使用 pd.to_datetime 并传入 format 参数或者自行写解析规则。如果解析失败把原始值打印出来逐条检查。5. 第二步用 pandas 生成多维度汇总表数据洗干净之后汇总就是顺理成章的事。这一节我们生成三张核心表区域汇总、产品汇总、销售员汇总。每张表都包含几个统一指标订单数、销售笔数、销量、销售额。指标定义如下订单数销售单号去重后的数量反映实际交易笔数销售笔数明细行数反映订单中包含的产品条目数销量所有明细行数量的总和销售额所有明细行单价乘以数量的总和# 文件路径summary_builder.py from data_loader import load_sales_data def build_summaries(df: pd.DataFrame): 基于明细数据生成多维汇总表 # 按区域汇总 region_summary df.groupby(区域).agg( 订单数(销售单号, nunique), 销售笔数(销售单号, count), 销量(数量, sum), 销售额(销售额, sum), ).reset_index().sort_values(销售额, ascendingFalse) # 按产品汇总 product_summary df.groupby(产品名称).agg( 订单数(销售单号, nunique), 销售笔数(销售单号, count), 销量(数量, sum), 销售额(销售额, sum), ).reset_index().sort_values(销售额, ascendingFalse) # 按销售员汇总 salesman_summary df.groupby(销售员).agg( 订单数(销售单号, nunique), 销售笔数(销售单号, count), 销量(数量, sum), 销售额(销售额, sum), ).reset_index().sort_values(销售额, ascendingFalse) return region_summary, product_summary, salesman_summary if __name__ __main__: sales_df load_sales_data(销售明细.xlsx) region, product, salesman build_summaries(sales_df) print(区域汇总) print(region)这里的关键点是 agg 函数的用法。“销售单号”同时被用于两种统计nunique 是去重计数count 是非空计数。如果你漏掉了 nunique订单数就会变成明细行数这在多行订单的场景下是不准确的。聚合结果会按照销售额降序排列这样领导看表的时候第一眼就能看到最重要的区域和产品。如果你还想看趋势可以继续按“月份区域”做分组生成一张透视表# 按月、区域查看销售额趋势 trend df.pivot_table( index月份, columns区域, values销售额, aggfuncsum, fill_value0 ) print(trend)透视表适合放在“趋势分析”附页中。不过要注意如果领导只要快速汇总不要过度炫技核心输出仍然应该是区域、产品、销售员三张精简表。6. 第三步把汇总结果交给大模型生成异常清单这一步是整个方案的精华。传统做法是分析人员盯着汇总表找异常眼力好的人能看出点东西但速度慢且容易漏。大模型可以在几秒钟内根据你给定的业务框架输出候选异常虽然不保证全部准确但足以大幅缩小排查范围。你可能会担心大模型分析表格数据靠谱吗它会不会瞎编答案是它会基于你给的数据文本做推理如果数据本身是结构化、有明确口径的它的分析通常是有价值的但它是概率模型没有真正理解业务所以输出必须经过人工确认。这也是为什么我把它定位成“异常候选助手”而不是“最终结论生成器”。合理的大模型提示词应该包含四个要素角色、任务、数据、输出格式。下面这段代码展示了如何调用 OpenAI 兼容接口并解析模型返回的 JSON。# 文件路径ai_analyzer.py import json import os from openai import OpenAI client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL, https://api.openai.com/v1), ) def analyze_anomalies(summary_df, group_col: str, metric: str 销售额): 调用大模型分析汇总数据中的异常 # 把 DataFrame 转成文本让模型能读到完整数据 data_text summary_df.to_string(indexFalse) prompt f 你是资深销售运营分析专家。下面是一份按 {group_col} 汇总的销售数据。 指标说明 - 订单数去重后的订单数量 - 销售笔数明细行数 - 销量商品总件数 - 销售额总销售金额 数据如下 {data_text} 请你基于以下思路找出值得关注的异常 1. 哪个分组的销售额显著高或显著低说明偏离幅度。 2. 是否存在长尾分布即少数分组贡献了大部分销售额。 3. 有没有其他你认为管理层应该关注的信号。 请严格输出 JSON 数组不要输出其他文字。每个元素格式如下 {{ group: 分组名称, level: high 或 medium 或 low, reason: 异常原因描述要具体到数字, suggest: 建议动作 }} response client.chat.completions.create( modelos.getenv(LLM_MODEL, gpt-4o-mini), messages[ {role: system, content: 你是一名严谨的数据分析助手只输出 JSON。}, {role: user, content: prompt}, ], temperature0.2, ) content response.choices[0].message.content return content细心的读者会发现我使用了环境变量来管理 API Key、base_url 和模型名。这样做避免了密钥泄露风险。你在运行前需要设置环境变量export LLM_API_KEY你的密钥 export LLM_BASE_URL模型服务地址 export LLM_MODEL模型名称Windows 下可以在命令行里用 set 设置set LLM_API_KEY你的密钥模型返回的内容不一定是干净的 JSON可能带有 markdown 代码块标记。所以在解析时需要一段容错代码# 文件路径parse_result.py import json def parse_llm_json(content: str): 解析大模型返回的 JSON兼容 markdown 代码块 text content.strip() if text.startswith(): text text.strip() if text.startswith(json): text text[4:] return json.loads(text)解析后的 JSON 是一个列表可以转换为 DataFrame方便后续写入 Excel。在模拟数据上运行模型很可能会指出某个区域或产品明显偏低并给出与该分组均值对比的偏离百分比。这类内容已经足够生成一份有信息量的异常清单。7. 第四步把汇总表和异常清单写入 Excel所有中间结果都准备好后最后一步是输出 Excel 文件。这里建议生成一个有多个 sheet 的工作簿结构如下区域汇总产品汇总销售员汇总异常清单说明使用 openpyxl 作为写入引擎代码如下# 文件路径excel_writer.py import pandas as pd from data_loader import load_sales_data from summary_builder import build_summaries from ai_analyzer import analyze_anomalies from parse_result import parse_llm_json def write_report(output_path: str): sales_df load_sales_data(销售明细.xlsx) region, product, salesman build_summaries(sales_df) # 让大模型分析区域汇总中的异常 anomaly_content analyze_anomalies(region, 区域, 销售额) anomalies parse_llm_json(anomaly_content) anomaly_df pd.DataFrame(anomalies) with pd.ExcelWriter(output_path, engineopenpyxl) as writer: region.to_excel(writer, sheet_name区域汇总, indexFalse) product.to_excel(writer, sheet_name产品汇总, indexFalse) salesman.to_excel(writer, sheet_name销售员汇总, indexFalse) anomaly_df.to_excel(writer, sheet_name异常清单, indexFalse) # 生成一个说明 sheet记录生成时间和口径 meta_df pd.DataFrame({ 项目: [生成时间, 数据来源, 异常分析模型], 内容: [ pd.Timestamp.now().strftime(%Y-%m-%d %H:%M:%S), 销售明细.xlsx, os.getenv(LLM_MODEL, 未知模型), ] }) meta_df.to_excel(writer, sheet_name说明, indexFalse) print(f报告已生成{output_path}) if __name__ __main__: write_report(销售分析报告.xlsx)在 Excel 中sheet 名称最大长度是 31 个字符中文完全没问题但注意不要使用反斜杠等非法字符。如果你的汇总表列特别多可以考虑冻结首行、调整列宽这些属于美化工作不影响数据分析本身。写完之后用 Excel 打开生成的文件你应该能看到四张有内容的表。异常清单中的 group 列对应区域名称level 表示严重程度reason 和 suggest 是模型生成的业务描述。8. 运行效果与结果验证把整个流程跑通预期的文件结构如下销售明细.xlsx 销售分析报告.xlsx data_loader.py summary_builder.py ai_analyzer.py parse_result.py excel_writer.py运行入口是 excel_writer.pypython excel_writer.py运行成功的标志控制台输出“报告已生成销售分析报告.xlsx”Excel 文件生成打开后包含五个 sheet区域汇总表按销售额降序排列异常清单中至少有三条记录每条都有 reason 和 suggest如果运行失败第一步看错误堆栈。常见错误分为三类权限问题、格式问题、网络问题。权限问题通常是文件被 Excel 占用关闭文件重试即可格式问题是日期或数值列无法解析需要打印前几行检查网络问题是大模型 API 超时或返回非 200 状态检查网络和 API Key 是否有效。关于异常清单质量有一条验证标准人工看一眼 reason 里的数字是否与区域汇总表一致。如果模型说“华东区域销售额占比达到 41%远超其他区域”你可以回到区域汇总表里核对占比。大模型偶尔会算错百分比这不是模型能力问题而是它不擅长精确计算。建议在提示词里要求模型只描述趋势不要过度量化或者只让它引用原始数据里的数值不做二次计算。9. 常见问题与排查思路这一部分整理实际运行中最高频的几类问题按现象、可能原因、排查方式、解决方案列出。问题现象可能原因排查方式解决方案pd.read_excel 报错文件不存在路径写错或文件未放在当前目录打印 os.getcwd() 查看当前路径使用绝对路径或把文件移到脚本目录日期列变成类似 45123 的数字Excel 日期序列号未被解析打印 df 的 dtypes检查销售日期列用 pd.to_datetime 并指定 origin1899-12-30订单数比销售笔数少一半每笔订单包含多行明细查看销售单号重复行数用 nunique 统计订单数不要用 count调用大模型报 AuthenticationErrorAPI Key 无效检查环境变量是否设置重新生成 Key并 export 后重启终端模型返回内容无法解析为 JSON提示词约束不够模型输出了多余文字打印返回的 content 原文增加“只输出JSON不输出其他文字”添加失败重试生成的 Excel 打不开openpyxl 和 pandas 版本兼容问题查看错误堆栈升级 pandas 和 openpyxl 到最新版还有一个很容易忽略的问题如果你直接代码里写死 API Key上传 GitHub 时会泄露密钥建议从一开始就用环境变量。真实的企业数据比代码更敏感绝不要把公司销售数据发给不受信任的第三方接口。10. 最佳实践与工程建议代码能跑通只是第一步。如果你想把这套流程用到月度汇总或周报上下面几个建议会让它更可靠。10.1 把提示词版本化管理提示词决定了异常分析的质量。同一套数据提示词写得清楚模型输出就有逻辑提示词比较随意输出就飘。建议把提示词单独放到一个配置文件里比如 prompt_config.py用变量保存。每次微调提示词通过文件名或版本号记录方便回溯。10.2 设置人工确认环节大模型的异常结果不能直接视为最终结论。更好的流程是脚本生成异常候选清单你逐条确认删除误报补充遗漏再生成终版汇报文件。后续如果你积累了足够的“实际确认过的异常案例”可以反过来优化提示词让模型越来越贴合你的业务。10.3 保持汇总逻辑与业务口径一致不同公司对销售额是否有不同定义这很关键。有的公司按订单金额计算有的扣除退款有的还要考虑折扣。所以不要把业务口径写死在聚合函数里而是单独用一个 constant 区域存放比如 SALES_COL 销售额。如果口径变了只改一处到处生效。10.4 增加环比或同比数据异常分析如果有环比或同比数据会更准。只有当月数据模型只能说“某区域占比低”有了上月数据模型可以说“某区域销售额环比下降 30%”。后者的参考价值明显更高。在月度汇总场景里建议把上期数据也放到提示词中。10.5 关注数据安全边界销售明细属于企业经营数据。在使用大模型 API 分析前务必确认以下几点你是否有权限把数据发送给第三方模型服务公司是否有禁止数据出域的规定API Key 是否设置了访问范围和配额限制本地脚本是否有日志脱敏策略如果公司有严格的数据合规要求建议把 base_url 指向内网部署的大模型服务或者改用本地开源模型。宁可慢一点也不能把核心数据暴露在不可控的环境中。10.6 从脚本到定时任务流程稳定后可以用系统自带的任务计划程序让脚本每天自动运行。Windows 下是任务计划程序Linux 下是 crontab。定时任务还可以顺带生成一份 CSV 式的结果文件方便后续接入企业微信或钉钉机器人把异常清单推送到群里。11. 总结与后续学习方向现在你已经有了一条完整路径读取销售明细、清洗数据、用 pandas 生成多维汇总、调用大模型产出异常候选、最后输出一个带多个 sheet 的 Excel 报告。整个过程不再依赖手工筛选和肉眼找异常时间成本从一两个小时降到几十分钟并且脚本可以复用。下一步可以往三个方向深入第一是学习 pandas 的 groupby 和聚合函数把更多维度的汇总掌握熟练比如渠道、门店、客户等级第二是研究提示词工程学会给大模型提供更精准的分析框架让异常清单更贴合领导关心的问题第三是补一些数据可视化基础用 Matplotlib 或 ReportLab 生成图表让汇总报告更直观。最后提醒一句AI 生成的东西一定要人工确认。销售数据关心的不只是数字对不对还有口径是否一致、表述是否准确。用 AI 提高效率用你自己的判断兜底这才是成熟的数据分析工作方式。等这套流程在月度汇报里习惯之后再遇到领导下午来要数据你就能从容很多。
返回列表