第2章 从工具认知到业务落地:Excel、Python与ChatGPT协同驱动的数据分析实践导论
数据分析这项工作,看上去是在处理数字,实际上是在回答业务问题。门店销量为什么下降,客户为什么不复购,库存为什么积压,活动为什么没有带来预期增长,这些问题的背后都离不开数据。很多人一开始接触数据分析时,往往把注意力放在公式、函数、代码或者图表上,但真正决定分析质量的,往往不是工具本身,而是三个更底层的能力:能不能把问题说清楚,能不能把数据整理干净,能不能把结果转化为行动。

在实际工作中,Excel、Python和ChatGPT并不是互相替代的关系,而是互相补位的关系。Excel适合快速查看、核对、汇报和轻量分析;Python适合批量处理、自动化计算和复杂建模;ChatGPT适合帮助人梳理问题、生成初版方案、改写代码、解释逻辑和提升沟通效率。三者组合起来,就不再是单纯的“会做表”,而是形成了一套更完整的数据分析工作流。

本章围绕这条主线展开:先讲工具协同背后的分析逻辑,再讲Excel与Python如何分工,再讲ChatGPT怎样参与到问题定义、代码生成和分析表达中,最后落到提示词设计和学习路径上。内容不仅讲概念,也穿插零售经营、客户运营、销售复盘等商业案例,并配套可运行的Python代码,帮助读者把理论和实务真正接起来。

2.1 本章导读:为什么数据分析越来越强调工具协同
过去不少企业做数据分析,依赖的是“一个熟练用Excel的人”。这种方式在数据量小、业务节奏慢的时候还能应付,但当企业的门店、商品、客户、订单、渠道同时增长时,人工复制、粘贴、筛选、汇总很快就会出现三个问题。

第一,效率跟不上。
如果每天要汇总二十家门店的数据、清洗几千条订单记录、对比多个时间周期,单靠手工操作不仅慢,而且容易出错。越是重复劳动,越需要自动化。

第二,结果难以复现。
很多人在Excel里做分析时,今天改了一列,明天复制了一块区域,后天又手动修了一些数,最后连自己都不清楚最终结果是怎么来的。这样的分析很难交接,也难以沉淀。

第三,业务解释不够深。
很多报表只能告诉管理者“发生了什么”,却解释不了“为什么会发生”以及“下一步应该怎么做”。这就需要把分析思路、指标体系和业务逻辑一起纳入工作流程。

因此,现代数据分析越来越强调工具协同。简单说,就是让不同工具各做自己最擅长的部分:

工具 最擅长的事 典型场景
Excel 快速查看、手工校验、透视汇总、图表展示 日报、周报、经营会议材料
Python 批量处理、清洗、计算、建模、自动导出 数据预处理、自动报表、预测分析
ChatGPT 问题拆解、提示词设计、代码生成、结果改写 方案草拟、代码辅助、分析说明
从本质上说,工具协同不是为了“显得高级”,而是为了形成一条更稳定的分析链路:
业务问题提出 -> 数据准备 -> 数据清洗 -> 指标计算 -> 结果解释 -> 报告输出 -> 业务动作执行。

谁能把这条链路打通,谁的数据分析能力就更接近真实工作场景。

2.2 Excel与Python结合的数据处理认知
2.2.1 先理解分析工作的底层逻辑
在讲工具之前,先要把数据分析的底层逻辑讲清楚。很多人学了很多函数、很多库,还是做不好分析,根本原因并不是不会操作,而是不知道分析究竟要解决什么。

一个完整的数据分析流程,通常包括以下几个环节:

明确业务问题
例如:最近三个月门店利润下滑,原因是什么?

定义分析目标
是看销售额、毛利、客单价、退货率,还是会员复购率?

识别数据来源
订单表、商品表、门店表、会员表、活动表、库存表。

处理数据质量问题
缺失值、重复值、格式不统一、异常值、时间口径不一致。

建立分析指标
比如销售额、毛利额、毛利率、单店产出、品类贡献率、复购率。

形成分析结论
例如:利润下滑不是因为销量下降,而是因为高毛利商品占比下降,且退货集中发生在两家门店。

转化为业务动作
优化商品结构、调整促销策略、复盘门店执行、强化会员召回。

这七步里,Excel、Python和ChatGPT其实都只是服务工具。真正的核心,是从“问题”走到“行动”。

从分析理论上看,企业常见的数据分析可以分为四类:

描述性分析:发生了什么
例如,本月销售额是多少,哪个门店排名第一。

诊断性分析:为什么发生
例如,销售额下降是因为客流减少,还是客单价下降。

预测性分析:未来可能会怎样
例如,下个月销量可能落在什么区间。

决策性分析:应该怎么做
例如,是否应该减少低毛利品类投放。

初学者最容易犯的错误,是一上来就想做预测,结果连基础数据都没整理好。正确顺序应该是先做描述,再做诊断,然后才考虑预测和决策。

所以,无论后面学的是Excel还是Python,第一原则都不变:
分析不是把表做漂亮,而是把业务问题拆成可以计算、可以验证、可以落地的任务。

2.2.2 用Excel完成日常表格分析与快速校验
Excel之所以在企业里长期稳定存在,不是因为它“简单”,而是因为它特别贴近业务人员的工作方式。一个销售主管、门店经理、采购专员,哪怕不会写代码,也能用Excel看数据、核数据、做汇报。这种低门槛,是Excel最大的价值。

Excel在数据分析中的典型优势,主要体现在五个方面。

一、可视化操作直观
筛选、排序、冻结窗格、条件格式、图表、透视表,几乎都可以通过点击完成。对非技术岗位来说,这种操作方式天然更容易上手。

二、适合小规模、快节奏分析
如果只有几百到几千条数据,Excel完全能胜任。比如门店日报、客服工单汇总、活动报名名单整理、销售员业绩排名,这些都可以快速完成。

三、核对和复查效率高
很多时候,真正耗时间的不是复杂计算,而是确认数据有没有问题。Excel在逐行查看、局部修正、人工标记方面非常方便,适合作为“最终检查台”。

四、透视表特别适合经营复盘
透视表本质上就是一种低门槛聚合分析工具。它可以快速把明细数据转换成“按门店、按品类、按日期、按员工、按区域”的汇总视角。这一点在经营分析中非常实用。

五、适合直接形成汇报材料
管理层看报表,不一定关心脚本是怎么写的,但一定关心结果是否清楚。Excel的图表、格式、颜色、布局天生适合会议材料输出。

不过,Excel也有明显边界。

数据量一大,性能下降明显。
手工步骤多,复用性差。
多人协作时版本容易混乱。
逻辑一复杂,公式维护成本会很高。
过程不透明,难以追溯。
以一个零售连锁企业为例。假设运营经理每天要汇总十家门店的销售表,内容包括销售额、退货单、会员订单、促销订单。刚开始门店少时,用Excel分别粘贴进总表,再做透视表,确实够用。但随着门店扩张到五十家,商品SKU增加到三千个,人工汇总就会出现以下问题:

不同门店字段不一致,有的写“销售金额”,有的写“实收金额”
日期格式混乱,有的是“2025/01/01”,有的是“2025-1-1”
商品名称存在别名,导致透视表统计失真
退货记录有的写成负数,有的单独标记
每天的分析步骤重复,但仍要手工操作
这时就说明:Excel还在发挥价值,但已经不能独立承担全部分析任务了。它更适合作为“前端交互和结果展示工具”,而不应该继续承担大量重复清洗工作。

因此,在企业实际应用中,Excel最合理的位置通常有三个:

作为原始数据收集与人工校验界面
作为分析结果承载与图表展示载体
作为业务人员和技术人员之间的沟通中间层
说得更直白一点,Excel不应该被淘汰,而应该被重新分工。

2.2.3 借助Python建立可复用的数据处理流程
如果说Excel解决的是“看得见、改得动”的问题,那么Python解决的是“做得快、做得稳、做得可重复”的问题。

Python在数据分析中的核心价值,不是“代码更高级”,而是它能把重复工作变成流程,把流程变成资产。今天处理一份表,明天处理十份表,后天处理一百份表,只要规则不变,脚本就能复用。

这背后对应的是现代数据分析非常重要的一个原则:可复现性。

所谓可复现性,简单理解就是同一份数据、同一套逻辑、同一段代码,不管什么时候运行,结果都应该一致。这样的分析才经得起复盘、审计和交接。

在商业场景里,Python尤其适合以下任务:

批量读取多个Excel文件
统一字段名和数据格式
清洗缺失值、重复值、异常值
自动计算KPI指标
多维度分组汇总
自动生成分析结果文件
连接数据库或接口拉取数据
进一步做预测、分类、聚类、推荐等模型任务
下面通过一个可直接运行的零售经营分析案例,说明Python怎样把日常报表工作做成自动化流程。

商业案例:连锁零售门店经营分析自动化
场景设定如下:

某连锁零售企业希望每周自动输出一份经营分析报告,关注以下问题:

总销售额、毛利额、毛利率表现如何
哪些门店贡献更高,哪些门店退货异常
哪些商品品类销量高但利润低
每日销售趋势是否存在明显波动
会员复购率处于什么水平
为了方便演示,下面的代码会先自动生成一份模拟销售数据,再完成清洗、计算、汇总和Excel导出。代码可在 VS Code 中直接运行。

示例代码:使用 pandas 与 openpyxl 自动生成经营分析报告
python
from future import annotations

import random
from datetime import datetime, timedelta
from pathlib import Path

import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Alignment
from openpyxl.styles import Font
from openpyxl.styles import PatternFill

def createSampleSalesFile(outputPath: str, rowCount: int = 1200) -> None:

random.seed(42)

storeNames = ["朝阳店", "国贸店", "望京店", "中关村店", "西单店"]
paymentTypes = ["微信", "支付宝", "现金", "银行卡"]

categoryProductMap = {
    "饮品": [("美式咖啡", 18), ("拿铁", 24), ("燕麦拿铁", 28), ("柠檬茶", 16)],
    "烘焙": [("牛角包", 12), ("芝士面包", 15), ("全麦吐司", 14)],
    "轻食": [("鸡胸沙拉", 29), ("金枪鱼三明治", 26), ("酸奶水果杯", 22)],
    "周边": [("保温杯", 79), ("帆布袋", 39), ("玻璃杯", 49)]
}

startDate = datetime(2025, 1, 1)
rows = []

for rowIndex in range(1, rowCount + 1):

    categoryName = random.choice(list(categoryProductMap.keys()))
    productName, basePrice = random.choice(categoryProductMap[categoryName])

    quantity = random.randint(1, 5)
    unitPrice = round(basePrice * random.uniform(0.95, 1.10), 2)
    costPrice = round(unitPrice * random.uniform(0.38, 0.62), 2)

    orderDate = startDate + timedelta(days=random.randint(0, 89))
    returnedFlag = 1 if random.random() < 0.05 else 0

    if random.random() < 0.75:
        memberId = f"M{random.randint(1001, 1100)}"
    else:
        memberId = None

    rows.append(
        {
            "OrderId": f"O{100000 + rowIndex}",
            "OrderDate": orderDate.strftime("%Y-%m-%d"),
            "StoreName": random.choice(storeNames),
            "ProductCategory": categoryName,
            "ProductName": productName,
            "Quantity": quantity,
            "UnitPrice": unitPrice,
            "CostPrice": costPrice,
            "MemberId": memberId,
            "PaymentType": random.choice(paymentTypes),
            "ReturnedFlag": returnedFlag
        }
    )

dataFrame = pd.DataFrame(rows)

if len(dataFrame) >= 6:

    dataFrame.loc[2, "UnitPrice"] = None
    dataFrame.loc[4, "Quantity"] = "3"
    dataFrame.loc[5, "OrderDate"] = "2025/01/09"

dataFrame.to_excel(outputPath, index=False)

class RetailAnalysisEngine:

def __init__(self, sourceFilePath: str) -> None:

    self.sourceFilePath = Path(sourceFilePath)

def loadData(self) -> pd.DataFrame:

    dataFrame = pd.read_excel(self.sourceFilePath)
    return dataFrame

def cleanData(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    workFrame = dataFrame.copy()

    workFrame["OrderDate"] = pd.to_datetime(workFrame["OrderDate"], errors="coerce")
    workFrame["Quantity"] = pd.to_numeric(workFrame["Quantity"], errors="coerce").fillna(0).astype(int)
    workFrame["UnitPrice"] = pd.to_numeric(workFrame["UnitPrice"], errors="coerce")
    workFrame["CostPrice"] = pd.to_numeric(workFrame["CostPrice"], errors="coerce")
    workFrame["ReturnedFlag"] = pd.to_numeric(workFrame["ReturnedFlag"], errors="coerce").fillna(0).astype(int)

    workFrame["UnitPrice"] = workFrame["UnitPrice"].fillna(
        workFrame.groupby("ProductCategory")["UnitPrice"].transform("median")
    )

    workFrame["CostPrice"] = workFrame["CostPrice"].fillna(workFrame["UnitPrice"] * 0.55)
    workFrame["MemberId"] = workFrame["MemberId"].fillna("Guest")

    workFrame = workFrame.dropna(
        subset=["OrderDate", "StoreName", "ProductCategory", "ProductName", "UnitPrice", "CostPrice"]
    )

    workFrame["SalesAmount"] = workFrame["Quantity"] * workFrame["UnitPrice"]
    workFrame["CostAmount"] = workFrame["Quantity"] * workFrame["CostPrice"]

    returnMask = workFrame["ReturnedFlag"] == 1

    workFrame.loc[returnMask, "SalesAmount"] = workFrame.loc[returnMask, "SalesAmount"] * -1
    workFrame.loc[returnMask, "CostAmount"] = workFrame.loc[returnMask, "CostAmount"] * -1

    workFrame["GrossProfit"] = workFrame["SalesAmount"] - workFrame["CostAmount"]
    workFrame["OrderMonth"] = workFrame["OrderDate"].dt.to_period("M").astype(str)
    workFrame["OrderDay"] = workFrame["OrderDate"].dt.date.astype(str)

    return workFrame

def buildSummary(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    totalSales = round(dataFrame["SalesAmount"].sum(), 2)
    totalProfit = round(dataFrame["GrossProfit"].sum(), 2)
    grossMargin = round(totalProfit / totalSales, 4) if totalSales != 0 else 0
    orderCount = int(dataFrame["OrderId"].nunique())
    avgOrderValue = round(totalSales / orderCount, 2) if orderCount != 0 else 0

    memberOrderFrame = (
        dataFrame[dataFrame["MemberId"] != "Guest"]
        .groupby("MemberId")["OrderId"]
        .nunique()
        .reset_index(name="OrderCount")
    )

    memberCount = int(memberOrderFrame["MemberId"].nunique())
    repeatMemberCount = int((memberOrderFrame["OrderCount"] >= 2).sum())
    repeatRate = round(repeatMemberCount / memberCount, 4) if memberCount != 0 else 0

    summaryFrame = pd.DataFrame(
        [
            {"MetricName": "净销售额", "MetricValue": totalSales},
            {"MetricName": "毛利额", "MetricValue": totalProfit},
            {"MetricName": "毛利率", "MetricValue": grossMargin},
            {"MetricName": "订单数", "MetricValue": orderCount},
            {"MetricName": "平均订单金额", "MetricValue": avgOrderValue},
            {"MetricName": "会员复购率", "MetricValue": repeatRate}
        ]
    )

    return summaryFrame

def buildStoreAnalysis(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    storeFrame = (
        dataFrame.groupby("StoreName")
        .agg(
            NetSales=("SalesAmount", "sum"),
            GrossProfit=("GrossProfit", "sum"),
            OrderCount=("OrderId", "nunique"),
            ReturnCount=("ReturnedFlag", "sum")
        )
        .reset_index()
    )

    storeFrame["GrossMargin"] = (
        storeFrame["GrossProfit"] / storeFrame["NetSales"].replace(0, pd.NA)
    ).round(4)

    storeFrame["AvgOrderValue"] = (
        storeFrame["NetSales"] / storeFrame["OrderCount"].replace(0, pd.NA)
    ).round(2)

    storeFrame = storeFrame.sort_values(by="NetSales", ascending=False)

    return storeFrame

def buildCategoryAnalysis(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    categoryFrame = (
        dataFrame.groupby("ProductCategory")
        .agg(
            NetSales=("SalesAmount", "sum"),
            GrossProfit=("GrossProfit", "sum"),
            Quantity=("Quantity", "sum"),
            ReturnCount=("ReturnedFlag", "sum")
        )
        .reset_index()
    )

    categoryFrame["GrossMargin"] = (
        categoryFrame["GrossProfit"] / categoryFrame["NetSales"].replace(0, pd.NA)
    ).round(4)

    categoryFrame = categoryFrame.sort_values(by="GrossProfit", ascending=False)

    return categoryFrame

def buildDailyTrend(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    dailyFrame = (
        dataFrame.groupby("OrderDay")
        .agg(
            NetSales=("SalesAmount", "sum"),
            GrossProfit=("GrossProfit", "sum"),
            OrderCount=("OrderId", "nunique")
        )
        .reset_index()
        .sort_values(by="OrderDay", ascending=True)
    )

    return dailyFrame

def buildMemberAnalysis(self, dataFrame: pd.DataFrame) -> pd.DataFrame:

    memberFrame = (
        dataFrame[dataFrame["MemberId"] != "Guest"]
        .groupby("MemberId")
        .agg(
            OrderCount=("OrderId", "nunique"),
            NetSales=("SalesAmount", "sum"),
            GrossProfit=("GrossProfit", "sum")
        )
        .reset_index()
    )

    memberFrame["IsRepeatMember"] = memberFrame["OrderCount"].apply(
        lambda value: "是" if value >= 2 else "否"
    )

    memberFrame = memberFrame.sort_values(by="NetSales", ascending=False)

    return memberFrame

def beautifyWorkbook(self, outputFilePath: str) -> None:

    workbook = load_workbook(outputFilePath)
    headerFill = PatternFill("solid", fgColor="1F4E78")
    headerFont = Font(color="FFFFFF", bold=True)
    centerAlignment = Alignment(horizontal="center", vertical="center")

    for sheetName in workbook.sheetnames:

        sheet = workbook[sheetName]
        sheet.freeze_panes = "A2"

        for cell in sheet[1]:

            cell.fill = headerFill
            cell.font = headerFont
            cell.alignment = centerAlignment

        for columnCells in sheet.columns:

            maxLength = 0
            columnLetter = columnCells[0].column_letter

            for cell in columnCells:

                cellValue = "" if cell.value is None else str(cell.value)

                if len(cellValue) > maxLength:

                    maxLength = len(cellValue)

            sheet.column_dimensions[columnLetter].width = maxLength + 4

    workbook.save(outputFilePath)

def exportReport(self, outputFilePath: str) -> None:

    rawFrame = self.loadData()
    cleanFrame = self.cleanData(rawFrame)
    summaryFrame = self.buildSummary(cleanFrame)
    storeFrame = self.buildStoreAnalysis(cleanFrame)
    categoryFrame = self.buildCategoryAnalysis(cleanFrame)
    dailyFrame = self.buildDailyTrend(cleanFrame)
    memberFrame = self.buildMemberAnalysis(cleanFrame)

    with pd.ExcelWriter(outputFilePath, engine="openpyxl") as writer:

        cleanFrame.to_excel(writer, sheet_name="CleanData", index=False)
        summaryFrame.to_excel(writer, sheet_name="Summary", index=False)
        storeFrame.to_excel(writer, sheet_name="StoreAnalysis", index=False)
        categoryFrame.to_excel(writer, sheet_name="CategoryAnalysis", index=False)
        dailyFrame.to_excel(writer, sheet_name="DailyTrend", index=False)
        memberFrame.to_excel(writer, sheet_name="MemberAnalysis", index=False)

    self.beautifyWorkbook(outputFilePath)

def main() -> None:

basePath = Path.cwd()
sourceFilePath = basePath / "sampleSalesData.xlsx"
reportFilePath = basePath / "retailAnalysisReport.xlsx"

createSampleSalesFile(str(sourceFilePath), rowCount=1200)

analysisEngine = RetailAnalysisEngine(str(sourceFilePath))
analysisEngine.exportReport(str(reportFilePath))

print(f"示例数据已生成:{sourceFilePath}")
print(f"分析报告已输出:{reportFilePath}")

if name == “main”:

main()

运行

运行说明
安装依赖:
bash
pip install pandas openpyxl

将代码保存为 retailAnalysis.py
在 VS Code 终端运行:
bash
python retailAnalysis.py

运行完成后,会生成两个文件:

sampleSalesData.xlsx
retailAnalysisReport.xlsx
这个案例体现了哪些分析原理
这段代码虽然不复杂,但已经包含了很多企业数据分析的基本原理。

第一,先清洗,再计算。
很多新手一拿到数据就直接汇总,结果日期没转好、数值是文本、空值没处理,最后得出的报表自然不可靠。分析的第一步永远是保证数据质量。

第二,指标必须可定义。
什么是销售额,什么是毛利,退货怎么处理,复购率怎么算,这些都不是代码问题,而是指标口径问题。口径不统一,分析结果就不具备可比性。

第三,汇总要服务决策。
不是所有汇总都值得做。门店分析是为了找经营差异,品类分析是为了看结构贡献,日趋势是为了看波动,会员分析是为了看留存。每个结果页都应该对应一个业务问题。

第四,输出要便于业务使用。
很多人写脚本只输出一个CSV文件,技术上没问题,但业务同事未必爱看。导出Excel并做基础格式处理,本质上是提高分析结果的可用性。

业务解读示例
假设报表跑出来后,发现以下现象:

国贸店净销售额高,但毛利率偏低
轻食品类销量不错,但毛利额贡献一般
周边商品销量不大,但毛利率高
某一周退货明显上升
会员复购率只有 32%
这时就可以形成更接近经营动作的判断:

高销售低毛利,可能说明门店做了较多低毛利促销
轻食适合作为引流商品,但不能承担利润核心角色
周边商品适合做组合销售,提高客单价和毛利
退货异常需要回看门店执行、商品质量或活动规则
会员复购率偏低,说明需要优化会员触达和二次购买链路
这就是数据分析真正的价值:不是展示数字,而是帮助业务做判断。

2.2.4 pandas、xlwings与OpenPyXL联动的实际价值
很多初学者在学习Python处理Excel时,容易陷入一个误区:以为只要学会一个库就够了。实际上,企业里常用的几个库并不是竞争关系,而是分工关系。

一、pandas:负责数据处理主流程
pandas最强的地方,在于表格型数据的读取、清洗、转换、分组、汇总和分析。它很像“能编程的超级透视表”,尤其适合处理结构化数据。

常见操作包括:

读取 Excel、CSV
过滤数据
填充空值
删除重复值
转换日期和数值格式
分组聚合
拼接和合并数据表
透视统计
绝大多数经营分析脚本,核心处理都离不开 pandas。

二、OpenPyXL:负责Excel文件层面的格式控制
pandas可以导出Excel,但如果你还想做这些事:

设置标题背景色
调整列宽
冻结首行
设置字体样式
合并单元格
设置条件格式
那么就需要 OpenPyXL。它更像是Python与Excel文件格式之间的桥梁,擅长“修饰工作簿”。

前面的自动化报表案例里,beautifyWorkbook() 方法就是一个典型的 OpenPyXL 用法。

三、xlwings:负责与本地Excel软件交互
xlwings和前两个库最大的不同,是它不只是操作文件,还可以操作正在运行的 Excel 应用程序。它适合以下场景:

把DataFrame直接写入打开的Excel工作簿
调用本地Excel对象
与业务同事已有的模板文件打通
结合 VBA 或现成模板进行自动填报
实现“Python计算,Excel展示”的混合工作流
如果企业里已经沉淀了大量复杂Excel模板,而你又不想全部推倒重来,那么 xlwings 非常有价值。

三个库怎么分工最合适
工具库 核心作用 适合做什么
pandas 数据计算与处理 清洗、汇总、分析、建模前准备
OpenPyXL Excel文件样式与结构控制 美化报表、设置格式、固定模板输出
xlwings 与本地Excel应用联动 模板驱动填报、交互式办公自动化
可以把它理解成一条流水线:

pandas负责“算”
OpenPyXL负责“排”
xlwings负责“连”
这三者组合起来,正好对应企业分析工作的三个真实需求:
算得出来、排得好看、接得上现有流程。

xlwings 可选示例:把门店分析结果写入本地Excel
下面是一段可选代码,演示如何把分析结果写入本地Excel。需要说明的是,这段代码依赖本机已安装 Microsoft Excel,适合 Windows 或 macOS 办公环境。

python
from future import annotations

from pathlib import Path

import pandas as pd
import xlwings as xw

def exportStoreSheetWithXlwings(reportPath: str) -> None:

reportFile = Path(reportPath)
storeFrame = pd.read_excel(reportFile, sheet_name="StoreAnalysis")

app = xw.App(visible=False, add_book=False)

try:

    book = app.books.add()
    sheet = book.sheets[0]
    sheet.name = "StoreAnalysis"

    sheet.range("A1").value = storeFrame.columns.tolist()
    sheet.range("A2").options(index=False, header=False).value = storeFrame

    sheet.autofit()
    outputPath = reportFile.parent / "storeAnalysisByXlwings.xlsx"
    book.save(outputPath)

    print(f"xlwings 输出完成:{outputPath}")

finally:

    app.quit()

运行

安装命令如下:

bash
pip install xlwings

如果企业场景里需要“保留现有Excel模板”,那么 xlwings 的价值就会非常突出。比如财务部有固定周报模板,销售部有固定区域报表模板,人力部门有月度统计模板,这些都可以由 Python 自动把数据写进去,而不是人工复制粘贴。

2.2.5 认识DataFrame与Series这两个核心对象
很多人学 pandas 时,最开始觉得函数很多、语法很杂,实际上真正需要先吃透的概念只有两个:Series 和 DataFrame。

一、Series是什么
Series可以理解成“一列带标签的数据”。
比如一列销售额、一列订单日期、一列商品名称,本质上都可以是 Series。

它有两个关键组成部分:


索引
举个简单例子,如果你把“朝阳店、国贸店、望京店”三个门店的销售额放在一列里,这一列就是一个 Series。

二、DataFrame是什么
DataFrame可以理解成“由多个Series组成的一张表”。
它有行索引和列索引,最像我们平时在Excel中看到的二维表。

比如一张订单表,包含订单号、日期、门店、商品、数量、单价,这整张表就是一个 DataFrame。

三、为什么这两个概念重要
因为你在 pandas 里做的绝大多数操作,本质上都是以下几类变换:

从 DataFrame 取出一列,得到 Series
对 Series 做运算
把多个 Series 组合成新的 DataFrame
对 DataFrame 做筛选、分组、聚合、排序
理解了这一点,很多代码就不再神秘。

四、简短示例:DataFrame 与 Series 基本操作
python
from future import annotations

import pandas as pd

def buildSimpleSalesFrame() -> pd.DataFrame:

salesFrame = pd.DataFrame(
    {
        "StoreName": ["朝阳店", "国贸店", "望京店", "朝阳店"],
        "SalesAmount": [1200, 1800, 1500, 900],
        "OrderCount": [45, 60, 52, 33]
    }
)

return salesFrame

def main() -> None:

salesFrame = buildSimpleSalesFrame()

salesSeries = salesFrame["SalesAmount"]
salesFrame["AvgTicket"] = salesFrame["SalesAmount"] / salesFrame["OrderCount"]

storeSummaryFrame = (
    salesFrame.groupby("StoreName")
    .agg(
        TotalSales=("SalesAmount", "sum"),
        TotalOrders=("OrderCount", "sum")
    )
    .reset_index()
)

print("原始数据:")
print(salesFrame)
print("\n销售额这一列Series:")
print(salesSeries)
print("\n按门店汇总后的DataFrame:")
print(storeSummaryFrame)

if name == “main”:

main()

运行

这个例子虽然简单,但把最核心的关系讲清楚了:

salesFrame[“SalesAmount”] 取出的是一个 Series
给 salesFrame[“AvgTicket”] 赋值,是在 DataFrame 里增加一列
groupby().agg() 是把明细表转换成汇总表
如果把 Excel 和 pandas 对照起来理解,会更容易上手:

Excel中的概念 pandas中的对应对象
一列数据 Series
一张工作表 DataFrame
筛选 条件过滤
透视表 groupby / pivot_table
公式列 新增计算列
五、分析角度上的理解
从业务上看,DataFrame 代表的是“事实表”,Series 代表的是“指标或字段”。
比如一张订单明细表就是事实表,里面的销售额、数量、成本、门店、客户编号等字段,就是构成分析视角的维度和指标。

所以,学 pandas 不是学一堆函数,而是在学习如何用程序表达“从明细到汇总、从数据到结论”的过程。

2.2.6 Python及常用扩展库的安装部署
要让代码在 VS Code 中稳定运行,环境准备不能草率。很多初学者觉得安装这件事不重要,真正写代码时报错才发现问题多半出在环境上,而不是逻辑上。

一、建议的基础环境
Python 版本:建议使用 Python 3.11 或 3.12
编辑器:VS Code 1.103.2
包管理:pip
虚拟环境:venv
二、为什么建议使用虚拟环境
虚拟环境的作用,是让每个项目有自己独立的依赖,不会互相污染。
比如一个项目用 pandas 2.2,另一个项目用旧版本,如果都装在全局环境里,就容易产生冲突。

三、推荐安装步骤
先在系统中安装 Python,并确认命令可用:

bash
python --version
pip --version

接着创建项目目录:

bash
mkdir DataAnalysisProject
cd DataAnalysisProject

创建虚拟环境:

bash
python -m venv .venv

激活虚拟环境:

Windows:

bash
.venv\Scripts\activate

macOS 或 Linux:

bash
source .venv/bin/activate

安装常用库:

bash
pip install pandas openpyxl xlwings matplotlib seaborn numpy

如果需要把依赖记录下来,可以执行:

bash
pip freeze > requirements.txt

以后换电脑或交给同事,只需要执行:

bash
pip install -r requirements.txt

四、VS Code 中的关键设置
打开项目目录后,建议完成以下操作:

安装 Python 扩展
选择正确的解释器,也就是刚创建的 .venv
打开终端,确认当前虚拟环境已启用
运行测试脚本,确认库安装成功
你可以新建一个 testEnv.py 文件,写入下面代码检查环境:

python
import pandas as pd
import openpyxl

print(“环境安装成功”)
print(pd.version)
print(openpyxl.version)

运行

五、安装时常见问题
问题1:python 命令找不到
通常是 Python 没有加入系统环境变量,或者安装时未勾选相关选项。

问题2:pip install 很慢
有时是网络问题,可以更换镜像源,但在正式项目中最好记录清楚依赖版本,避免环境不一致。

问题3:VS Code 运行时报错,但终端能运行
通常是 VS Code 没有选择对的 Python 解释器。

问题4:xlwings 安装成功但运行报错
多半是本机没有安装 Excel,或者Excel版本与系统环境存在兼容问题。

六、环境本身也是项目资产
很多人做分析只保存了代码,没有保存环境说明,导致自己过一段时间重新运行都困难。真正规范的项目,应至少包含:

源代码
示例数据或字段说明
依赖文件
运行说明
输出示例
这样项目才具备可复用价值。

2.2.7 认识Python IDLE与VS Code工作环境
虽然现代开发和分析更多使用 VS Code、PyCharm 这样的编辑器,但 IDLE 仍然有它的价值,尤其是在初学阶段。

一、IDLE 的特点
IDLE 是 Python 自带的轻量编程环境。它的优点是:

安装 Python 后通常即可使用
界面简单,适合测试小段代码
适合学习基本语法、函数、循环、条件判断
启动快,依赖少
如果你只是想验证某段语句是否正确,或者做最初的语言练习,IDLE 很方便。

二、VS Code 更适合正式分析项目
一旦进入真实业务项目,VS Code 的优势会明显得多:

支持项目级目录管理
支持虚拟环境切换
支持调试、断点、变量查看
支持Git版本控制
支持插件扩展
支持终端操作和批量文件处理
对于数据分析来说,VS Code 的价值不仅在“写代码”,更在于它能够承载完整项目流程。

三、两者如何分工
可以这样理解:

IDLE适合“学语法、做小实验”
VS Code适合“做项目、跑脚本、交付结果”
如果是初学者,先在 IDLE 中验证基础语法,再转到 VS Code 做完整项目,是比较平滑的路径。

四、实际工作中的建议
如果你面向商业分析开发,建议尽快以 VS Code 为主。原因很简单:
企业里的数据分析任务往往不是写几行代码就结束,而是需要保存脚本、维护版本、处理多个文件、输出报表、记录依赖。只有项目化工作方式,才能支撑长期使用。

2.3 ChatGPT协助分析的基本方法
2.3.1 先把问题变成可分析的任务
很多人使用ChatGPT效果不好,并不是工具问题,而是输入的问题本身就不清楚。
比如一句“帮我分析一下销量下降原因”,这类说法太模糊,里面至少有五个不明确点:

什么时间段下降
下降的是销量、销售额还是利润
分析对象是单店、区域还是全公司
有哪些可用字段
输出希望得到代码、思路、报表还是结论
所以,在借助ChatGPT之前,要先把模糊问题改写成可分析任务。

以“销量下降”为例,一个更合格的任务定义应该至少包括:

业务背景:连锁咖啡门店近三个月利润下降
分析目标:找到利润下降主因
数据范围:订单表、商品表、门店表、活动表
核心字段:日期、门店、品类、销售额、成本、活动标签、退货标记
输出形式:分析思路、Python代码、结论模板
约束要求:变量名驼峰式命名,兼容 Python 3.11
这种改写,本质上就是把自然语言问题转成半结构化需求。
谁能把需求说清楚,谁就更容易得到可用结果。

从管理学视角看,这其实也是需求分析能力。数据分析做得好的人,往往不只是会算,而是会提问、会定义、会限定边界。

2.3.2 ChatGPT是什么,它在分析工作中能做什么
在数据分析工作里,ChatGPT更像一个“高响应速度的分析助理”。它不能替代业务判断,但可以显著缩短从问题到初稿的时间。

它常见的作用有以下几类。

一、帮助梳理分析思路
当你面对一个复杂问题,比如“为什么某地区复购率下降”,一时没有完整思路时,可以让它先帮你拆问题:

先看客户数量是否减少
再看新老客户结构变化
再看订单频次是否下降
再看促销活动是否中断
再看不同品类购买链路是否变化
这种拆解非常有价值,因为很多分析的难点不是不会算,而是不知道该从哪里开始。

二、帮助生成代码初稿
比如你已经明确要用 pandas 做门店维度汇总,但不想从头敲代码,那么可以让它先生成一个初版,再由你根据实际字段调整。

三、帮助解释代码和结果
有时候别人写了一段代码,你接手时看不懂,这时可以让它逐段解释。
同理,报表跑出来后,也可以让它把技术结果改写成适合业务汇报的话术。

四、帮助优化表达
分析报告常见问题不是内容不够,而是写得太技术化。
比如“字段经groupby后做聚合计算得出同比下降”,业务同事未必爱看。改成“同店客流下降叠加高毛利商品占比下滑,是本月利润走弱的主要原因”,表达就更适合管理场景。

五、帮助做提示词模板沉淀
高频任务如果每次都重新描述,会很浪费时间。
把常见分析任务整理成模板,比如销售分析模板、库存分析模板、会员分析模板,后续直接替换字段和场景即可。

不过也要注意,ChatGPT在分析工作中的最佳定位是:

帮你提速
帮你拆解
帮你起草
帮你润色
但真正负责口径确认、数据真实性和业务判断的,仍然是分析人员本人。

2.3.3 想获得更合适的答案,先学会写清提示
提示词写得好不好,直接决定结果能不能落地。
一个高质量提示词,通常至少包括六个元素:

角色或背景
任务目标
数据结构
输出要求
约束条件
风格要求
例如,同样是让它生成代码,下面两种写法效果差别会很大。

模糊写法
帮我写个销售分析代码。

这种提示的问题是:
没有业务背景、没有字段信息、没有输出目标、没有代码规范,得到的往往只能是通用示例。

清晰写法
请基于零售门店订单数据编写一段Python代码,使用 pandas 完成数据清洗和经营分析。
字段包括:OrderId、OrderDate、StoreName、ProductCategory、ProductName、Quantity、UnitPrice、CostPrice、MemberId、ReturnedFlag。
请输出:

总销售额、毛利额、毛利率、订单数、平均订单金额
按门店汇总的销售与毛利分析
按品类汇总的利润贡献分析
每日销售趋势表
代码要求兼容 Python 3.11,可在 VS Code 中运行,函数名和变量名采用驼峰命名法,代码结构清晰,并加入必要注释。
后者的优点就在于,它把“想要什么”说清楚了。
对方不需要猜,输出自然更贴合需求。

提示词设计的实用原则
不要只说主题,要说任务
不要只说任务,要说数据
不要只说数据,要说输出
不要只说输出,要说约束
不要只说约束,要说使用场景
一句话概括就是:
把提示词写成需求说明书,而不是一句口头指令。

2.3.4 借助ChatGPT生成、检查与改写代码
很多人把“生成代码”当作ChatGPT最主要的用途,其实更有价值的,是“生成初稿后继续检查和改写”。

因为在真实项目中,第一版代码通常都不是最终版本。真正有效的工作方式是四步:

先生成可运行初稿
用样例数据验证
根据报错和字段差异修正
再做性能、结构和表达优化
也就是说,正确姿势不是“一次性生成完美代码”,而是“通过多轮迭代加快开发”。

下面给出一个客户价值分析的小型商业案例,说明如何把分析代码从“会跑”推进到“有业务意义”。

商业案例:会员RFM价值分层
RFM 是客户运营中最常见的一种分层方法:

R:Recency,最近一次购买距离今天多久
F:Frequency,购买频次高不高
M:Monetary,消费金额高不高
企业通过 RFM 可以把会员分成高价值客户、沉睡客户、潜力客户等,从而匹配不同运营策略。

下面是一段可直接运行的RFM示例代码,使用前面生成的 sampleSalesData.xlsx 即可。

python
from future import annotations

from pathlib import Path

import pandas as pd

class CustomerRfmAnalyzer:

def __init__(self, sourceFilePath: str) -> None:

    self.sourceFilePath = Path(sourceFilePath)

def loadAndCleanData(self) -> pd.DataFrame:

    dataFrame = pd.read_excel(self.sourceFilePath)

    dataFrame["OrderDate"] = pd.to_datetime(dataFrame["OrderDate"], errors="coerce")
    dataFrame["Quantity"] = pd.to_numeric(dataFrame["Quantity"], errors="coerce").fillna(0)
    dataFrame["UnitPrice"] = pd.to_numeric(dataFrame["UnitPrice"], errors="coerce")
    dataFrame["ReturnedFlag"] = pd.to_numeric(dataFrame["ReturnedFlag"], errors="coerce").fillna(0).astype(int)
    dataFrame["MemberId"] = dataFrame["MemberId"].fillna("Guest")

    dataFrame = dataFrame.dropna(subset=["OrderDate", "UnitPrice"])
    dataFrame = dataFrame[dataFrame["MemberId"] != "Guest"].copy()

    dataFrame["SalesAmount"] = dataFrame["Quantity"] * dataFrame["UnitPrice"]
    dataFrame.loc[dataFrame["ReturnedFlag"] == 1, "SalesAmount"] = (
        dataFrame.loc[dataFrame["ReturnedFlag"] == 1, "SalesAmount"] * -1
    )

    return dataFrame

def scoreByQuantile(self, series: pd.Series, reverseScore: bool = False) -> pd.Series:

    rankSeries = series.rank(method="first")

    if reverseScore:

        scoreSeries = pd.qcut(rankSeries, 5, labels=[5, 4, 3, 2, 1])
    else:

        scoreSeries = pd.qcut(rankSeries, 5, labels=[1, 2, 3, 4, 5])

    return scoreSeries.astype(int)

def buildRfmResult(self) -> pd.DataFrame:

    dataFrame = self.loadAndCleanData()
    snapshotDate = dataFrame["OrderDate"].max() + pd.Timedelta(days=1)

    rfmFrame = (
        dataFrame.groupby("MemberId")
        .agg(
            LastOrderDate=("OrderDate", "max"),
            Frequency=("OrderId", "nunique"),
            Monetary=("SalesAmount", "sum")
        )
        .reset_index()
    )

    rfmFrame["RecencyDays"] = (snapshotDate - rfmFrame["LastOrderDate"]).dt.days

    rfmFrame["RScore"] = self.scoreByQuantile(rfmFrame["RecencyDays"], reverseScore=True)
    rfmFrame["FScore"] = self.scoreByQuantile(rfmFrame["Frequency"])
    rfmFrame["MScore"] = self.scoreByQuantile(rfmFrame["Monetary"])

    rfmFrame["TotalScore"] = rfmFrame["RScore"] + rfmFrame["FScore"] + rfmFrame["MScore"]

    def mapSegment(totalScore: int) -> str:

        if totalScore >= 13:

            return "高价值客户"

        if totalScore >= 10:

            return "潜力成长客户"

        if totalScore >= 7:

            return "普通维护客户"

        return "沉睡预警客户"

    rfmFrame["CustomerSegment"] = rfmFrame["TotalScore"].apply(mapSegment)
    rfmFrame = rfmFrame.sort_values(by="TotalScore", ascending=False)

    return rfmFrame

def main() -> None:

sourceFilePath = Path.cwd() / "sampleSalesData.xlsx"
analyzer = CustomerRfmAnalyzer(str(sourceFilePath))
resultFrame = analyzer.buildRfmResult()

outputPath = Path.cwd() / "customerRfmReport.xlsx"
resultFrame.to_excel(outputPath, index=False)

print(resultFrame.head(10))
print(f"RFM分析结果已输出:{outputPath}")

if name == “main”:

main()

运行

这段代码背后的业务意义
RFM之所以常用,不是因为公式复杂,而是因为它把客户价值拆成了三个最核心维度:

最近有没有买
买得频不频繁
买得多不多
对经营来说,这三件事对应的动作很明确:

高价值客户:重点维护,提供会员权益和新品优先体验
潜力成长客户:加强转化,推动第二次、第三次购买
普通维护客户:维持日常触达,避免流失
沉睡预警客户:做召回活动,分析流失原因
这说明一件事:代码只是工具,真正关键的是指标和业务策略之间是否形成闭环。

生成代码时要特别注意什么
使用ChatGPT辅助代码开发时,至少要注意以下几点:

不要直接拿陌生代码上线,要先用样例数据测试
要核对字段名是否和实际数据一致
要检查异常处理是否充分
要检查时间、金额、空值、重复值的处理是否合理
要补上日志、注释和输出说明
换句话说,ChatGPT最擅长的是把“从零到一”加速,但把“一变成可交付成果”,仍然需要人为把关。

2.3.5 面向业务重述问题与搭建提示模板
数据分析做不好,往往不是因为算不出来,而是因为问题问偏了。
企业里的很多问题看似在问“结果”,其实真正应该问的是“结构、过程和原因”。

下面看几个典型例子。

例子一:原问题不够好
为什么最近销售变差了?

这个问题的问题在于:

时间不明确
范围不明确
指标不明确
比较对象不明确
更合理的改写可以是:

请分析 2025 年第一季度与 2024 年第四季度相比,华北区域门店销售额和毛利额下降的主要原因。请分别从门店、品类、会员、促销活动和退货情况五个维度展开,并给出需要优先核查的指标清单。

这样的提问更容易得到可执行的分析框架。

例子二:从“看数据”改成“做决策”
原问题:

帮我做一个库存分析。

改写后:

请基于商品库存表、销售表和采购表,设计一套库存分析思路,重点识别高库存低周转商品、潜在缺货商品和采购节奏异常商品,并给出适合周报展示的核心指标与Python实现思路。

这时,任务目标已经从“分析一下”变成了“识别问题并支持动作”。

通用提示模板
下面是一套适合数据分析场景的提示模板,可直接复用:

text
你现在扮演企业数据分析顾问。

业务背景:
[描述业务场景,例如零售、会员、电商、供应链]

分析目标:
[说明要解决的核心问题]

数据表与字段:
[列出表名、字段名、字段含义]

希望输出:

  1. 分析思路
  2. 关键指标定义
  3. Python代码
  4. 结果解读建议
  5. 可视化建议

约束条件:

  • 使用 Python 3.11
  • 代码可在 VS Code 中运行
  • 函数名和变量名使用驼峰命名法
  • 代码结构清晰
  • 输出语言通俗易懂

这样的模板好处有两个:

每次只需要替换业务背景和字段
输出结果会更稳定、更接近实际需求
从长期看,提示模板本身也是一种分析资产。沉淀得越多,工作效率越高。

2.3.6 使用ChatGPT做数据分析的一套通用步骤
把ChatGPT真正融入分析工作,可以按下面这套流程来走。

第一步:先写业务问题,不要急着写代码
先问自己三件事:

业务到底要知道什么
分析结果给谁看
看完后要做什么动作
这一步做不好,后面所有代码都可能跑偏。

第二步:列出数据字段和口径
把关键字段整理清楚,尤其是:

主键是什么
时间字段是什么
金额字段口径是什么
退货、取消、作废如何处理
是否有空值和异常值
这一步决定分析是否可靠。

第三步:让ChatGPT先给分析框架
不要一上来就要代码,先要思路。
比如让它先列维度、指标、分析顺序、可能原因,这样更有利于你判断路线对不对。

第四步:再让它生成代码初稿
此时再进入代码阶段,效果会更稳。
因为你已经知道要算什么,而不是盲目索要脚本。

第五步:用样例数据做验证
验证至少要看三件事:

代码能不能运行
结果有没有明显异常
指标是否符合业务口径
第六步:让它帮你优化表达和报告
代码跑通后,还可以让它帮你把结果改写成:

管理层汇报版
业务部门复盘版
项目文档说明版
培训材料版
第七步:沉淀成模板
每完成一次典型任务,就把以下内容保存下来:

提示词模板
字段说明模板
代码模板
报告模板
常见问题清单
长期下来,你的分析能力就不再只是“会做一次”,而是“会复用很多次”。

2.4 提示词设计的实战技巧
2.4.1 提示词不是命令,而是需求说明书
很多人把提示词理解成一句命令,比如“帮我写代码”“帮我分析数据”。这种写法的问题是,它只给了动作,没有给上下文。

而在真实工作中,一个合格需求至少要说明:

谁在用
用来解决什么问题
数据长什么样
输出长什么样
有哪些规则不能违反
所以,写提示词时最好把自己当作项目需求提出者,而不是聊天提问者。

比如下面这个提示词就更像需求说明书:

我需要为连锁零售企业做一份经营分析脚本。
数据来自Excel订单表,字段包括门店、订单日期、商品品类、商品名称、数量、单价、成本、会员编号和退货标记。
请使用 pandas 编写可运行的Python代码,完成数据清洗、门店汇总、品类汇总、每日趋势分析,并导出到Excel。
代码要求兼容 Python 3.11,可在 VS Code 中运行,函数名和变量名使用驼峰命名法,输出结果便于业务同事阅读。

这类写法的本质,是把“我想要什么”完整交代出来。

2.4.2 通用写法上的基础技巧
高质量提示词通常有几个通用技巧。

一、写清目标,不写空话
“帮我分析一下”这种写法太宽泛。
应该改成“请识别利润下降原因”“请计算复购率并做客户分层”“请比较活动前后转化变化”。

二、限定对象和范围
比如:

时间范围:近30天、本季度、去年同期
分析对象:单店、区域、全渠道、某商品线
数据范围:订单表、会员表、库存表
范围越清楚,结果越实用。

三、说明输出形式
你到底要的是:

思路
代码
SQL
解释
汇报文案
图表建议
整体方案
输出形式不说清楚,很容易出现“你想要方案,它却给你代码”的情况。

四、提前写上约束条件
例如:

代码兼容 Python 3.11
使用 pandas
输出成表格
解释面向业务人员
变量名使用驼峰命名法
这些约束越明确,返工越少。

2.4.3 与数据场景相关的描述方法
数据分析类提示词和普通聊天最大的差别,在于它需要更强的数据上下文。
描述数据时,建议至少说明以下内容:

表名或数据来源
字段名
字段含义
数据粒度
时间范围
可能存在的数据问题
例如:

订单表粒度为订单明细行,一笔订单可能包含多个商品。
字段 OrderDate 为下单日期,ReturnedFlag 表示是否退货,退货订单仍保留在原表中。
SalesAmount 需要由数量乘以单价计算,若为退货则按负值处理。
数据时间范围为 2025 年 1 月到 2025 年 3 月。

这种描述非常关键,因为它直接关系到汇总逻辑。
例如,一笔订单多商品和一笔订单一行,在订单数计算上就完全不同;退货是否记负值,也会直接影响销售额和毛利口径。

数据提示里最容易漏掉的内容
粒度
去重规则
时间字段定义
状态字段含义
缺失值处理规则
而这些恰恰是最影响结果准确性的内容。

2.4.4 与表达风格相关的控制技巧
同样一份分析结果,面向不同对象,表达方式应该不同。

面向管理层
要点是简洁、结论先行、突出动作。
比如:

利润下滑的三大原因
建议优先处理的两项动作
风险点和机会点
面向业务同事
要点是可执行、接地气、能落地。
比如:

哪些门店需要重点复盘
哪些商品适合调整陈列
哪类会员需要重点召回
面向技术团队
要点是逻辑清晰、字段明确、流程可复现。
比如:

数据来源
清洗规则
指标定义
代码结构
运行步骤
因此,在提示词中加入表达风格要求非常必要。
例如:

请用经营汇报口吻总结
请用通俗语言解释,不要堆术语
请适合给管理层做周会汇报
请用技术文档风格输出步骤和代码
这样能显著提高结果可用性。

2.4.5 与输出形式相关的约束方式
很多时候,结果“不好用”不是因为内容不对,而是因为格式不对。
所以,输出形式一定要提前约束。

常见约束方式包括:

请分点输出
请先给思路,再给代码
请以Markdown表格展示指标定义
请输出完整可运行代码
请附上运行说明
请增加示例数据
请加入异常处理
请给出图表推荐方案
下面是一个更完整的输出约束示例:

请按以下顺序输出:

业务理解
分析思路
指标说明
Python代码
结果解读示例
常见错误提醒
这种格式特别适合实际项目,因为它覆盖了从“理解”到“交付”的完整过程。

2.4.6 提升效率的拆分与迭代方法
复杂任务不要一次性提完,最好拆分。
这是提高成功率和节省返工时间的关键。

一、按阶段拆
例如一个完整经营分析任务,可以拆成:

先做问题定义
再做指标设计
再做字段映射
再做代码生成
再做结果解读
最后做汇报改写
二、按模块拆
例如:

先做门店分析
再做品类分析
再做会员分析
最后汇总成报告
三、按角色拆
例如同一份结果,可以分别生成:

技术版说明
业务版说明
管理层汇报版说明
拆分的好处在于,每次聚焦一个目标,更容易把细节做对。
尤其当字段多、逻辑复杂时,分步推进比一次性输出更可靠。

四、把错误也当作输入的一部分
如果代码运行报错,不要只说“报错了”,而要把以下内容一并提供:

报错完整信息
相关代码片段
当前字段名
预期结果
这样下一轮修正会更快。

2.4.7 中英文混合环境下的语言处理建议
数据分析工作里经常会遇到中英文混合环境:

字段名是英文
报告要写中文
库函数是英文
业务术语可能是中英混排
这时最重要的是统一规范,避免一会儿一个说法。

建议一:字段名保持稳定
代码中的字段名最好和原始数据一致,避免中途随意改来改去。
如果原始字段名是英文,可以在报告里再用中文解释。

建议二:业务术语保持一致
例如:

GrossMargin 固定解释为“毛利率”
RepeatRate 固定解释为“复购率”
InventoryTurnover 固定解释为“库存周转率”
不要同一份文档里一会儿写“回购率”,一会儿写“复购率”,否则会影响理解。

建议三:提示词中可以明确要求语言风格
例如:

代码变量用英文驼峰命名
结果解释用中文
指标表头输出中英文对照
图表标题用中文
建议四:跨团队协作时保留字段字典
字段字典至少包括:

字段名
中文含义
数据类型
是否主键
口径说明
示例值
这会极大提高沟通效率,也能减少误解。

2.5 本章的学习路径与实践建议
2.5.1 先学什么,再练什么
很多人学数据分析时容易焦虑,感觉要学的东西很多:Excel函数、pandas、SQL、可视化、机器学习、提示词设计、自动化报表,结果学得越多越乱。更有效的方式,是按工作链路来学。

推荐的顺序如下:

第一阶段:先建立分析意识
先搞清楚以下问题:

什么是业务问题
什么是指标
什么是数据粒度
什么是口径统一
什么是清洗、汇总、解释和输出
没有这些基础,工具学再多也会散。

第二阶段:先把Excel用熟
至少掌握:

常用函数
数据透视表
条件格式
图表
文本分列
去重
筛选与排序
这是很多分析工作的第一层基础。

第三阶段:再学Python做自动化
重点掌握:

基础语法
读写Excel与CSV
pandas数据处理
分组汇总
结果导出
异常处理
到这一步,已经可以解决大量日常经营分析任务。

第四阶段:让ChatGPT参与流程
重点练三个能力:

把问题说清楚
把字段描述清楚
把输出要求限定清楚
这一步会显著提高分析效率。

第五阶段:做项目化练习
建议至少做这几类练习:

销售经营分析
客户复购分析
商品品类分析
库存周转分析
活动效果分析
每做完一个项目,就沉淀一套模板。长期积累后,能力提升会非常快。

2.5.2 不同类型读者的学习路线
不同背景的人,学习重点应当不同。

一、业务管理者
重点不一定是亲自写代码,而是理解:

数据分析能解决什么问题
指标体系怎么搭
如何看懂分析结论
如何提出高质量分析需求
管理者如果能把问题提对,团队效率会提升很多。

二、Excel基础较强的运营人员
这类读者的优势是熟悉业务和表格,最适合向“Python自动化分析”进阶。
建议路径是:

保留Excel做结果查看
用Python替代重复整理工作
用ChatGPT辅助生成初版脚本
这样转型成本相对最低。

三、Python初学者
这类读者不要急着做复杂模型,应先掌握:

pandas读写
清洗规则
分组汇总
Excel输出
结果解释
先能把经营周报自动跑出来,再谈更复杂的预测和建模。

四、数据分析岗位从业者
建议把重点放在三件事上:

业务理解深度
代码复用能力
提示词工程化能力
真正拉开差距的,往往不是会不会写 groupby,而是能不能把业务问题转成稳定可复用的分析框架。

五、需要做商业交付的开发人员
如果需要面向企业做项目交付,建议重点加强:

项目结构组织
环境管理
模块化代码
字段字典和文档
错误处理
输出模板
商业项目最怕的不是写不出,而是交付后维护不了。

2.5.3 使用提示词和代码时常见问题及应对办法
在实际使用过程中,最常见的问题大致有以下几类。

问题一:提示词太笼统,结果不贴需求
表现:

输出太空泛
代码字段不对
解释不符合业务场景
解决办法:

明确业务背景
列出字段名和字段含义
说明输出形式和约束条件
问题二:代码能运行,但结果不可信
表现:

汇总结果与Excel核对不一致
订单数明显异常
金额正负号处理错误
解决办法:

检查数据粒度
检查去重规则
检查退货、取消、作废口径
先抽样验证,再全量运行
问题三:环境问题导致脚本跑不起来
表现:

模块找不到
解释器错误
Excel库版本不兼容
解决办法:

固定Python版本
使用虚拟环境
保存 requirements.txt
在项目文档中写清运行步骤
问题四:输出结果有数字,但没有结论
表现:

报表很多,业务不知道看什么
图表不少,但没有行动建议
解决办法:

每个结果页只服务一个问题
结论要回答“为什么”和“怎么办”
报告中加入重点发现和建议动作
问题五:ChatGPT生成内容看起来正确,但细节有误
表现:

字段名编造
指标口径默认错误
边界条件未考虑
解决办法:

不要直接照搬
用样例数据校验
逐条核对字段与业务规则
把错误信息作为下一轮输入继续修正
问题六:分析做完后无法沉淀复用
表现:

下次还要从头做
同类任务重复劳动
不同人做法差异大
解决办法:

保存代码模板
保存提示词模板
建立字段字典
建立结果解释模板
建立常见问题清单
问题七:技术结果和业务语言脱节
表现:

技术同事看得懂,业务同事看不懂
结论过于术语化
解决办法:

输出两套版本:技术版和业务版
多用经营语言解释指标变化
少堆函数名和处理细节,多讲业务意义
从长期工作经验看,数据分析最重要的不是某一个函数,也不是某一种工具,而是三件事:

能把问题定义清楚
能把数据处理稳定
能把结果说成人能用的话
只要这三件事建立起来,Excel、Python和ChatGPT都能成为真正有生产力的工具,而不是堆在简历上的名词。

本章小结
本章的重点,不是单独讲某个工具怎么用,而是讲清楚三者如何形成一套完整的数据分析方法。

可以把核心结论归纳为以下几点:

数据分析的起点不是代码,而是业务问题。
Excel适合快速查看、核对和汇报,Python适合批量处理和自动化,ChatGPT适合问题拆解、代码辅助和表达优化。
pandas、OpenPyXL、xlwings分别对应“算、排、连”三种能力,组合使用更贴近企业实务。
DataFrame 和 Series 是理解 pandas 的关键起点。
提示词不是一句命令,而是一份需求说明书。
高质量分析必须把概念、指标、代码和业务动作连成闭环。
真正有价值的不是做出一次报表,而是形成可复用、可交付、可迭代的分析流程。
如果把本章的内容真正吃透,后续无论做销售分析、会员分析、库存分析还是经营复盘,都会更容易上手。因为你已经掌握的,不再只是某一个工具,而是一整套从问题定义到业务落地的分析框架。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐