实战一:电商销售数据全流程分析——从 CSV 到可视化报告

前 12 篇把工具都讲了,这篇把所有东西串起来——用真实数据分析场景,从读数据到出报告,全流程走一遍。

第一步:造一份模拟数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid")

# 生成一年电商订单数据
np.random.seed(42)
n = 3000

df = pd.DataFrame({
    "order_id": range(10000, 10000 + n),
    "date": np.random.choice(pd.date_range("2025-01-01", "2025-12-31", freq="D"), n),
    "product": np.random.choice(["手机", "电脑", "耳机", "平板", "手表"], n, p=[0.2, 0.15, 0.3, 0.2, 0.15]),
    "category": np.random.choice(["电子", "配件"], n, p=[0.6, 0.4]),
    "channel": np.random.choice(["线上", "线下"], n, p=[0.7, 0.3]),
    "city": np.random.choice(["北京", "上海", "广州", "深圳", "杭州", "成都"], n),
    "quantity": np.random.randint(1, 5, n),
    "unit_price": 0,  # 后面填
})

# 各产品定价
prices = {"手机": 3999, "电脑": 5999, "耳机": 299, "平板": 3299, "手表": 1599}
df["unit_price"] = df["product"].map(prices)
df["total_amount"] = df["quantity"] * df["unit_price"]

# 加一些"脏数据"
df.loc[np.random.choice(n, 20), "total_amount"] = np.nan  # 缺失值
df.loc[np.random.choice(n, 5), "quantity"] = -1            # 异常值
df.loc[np.random.choice(n, 30), "city"] = ""               # 空城市

print(f"数据量: {len(df)} 行")
print(df.head())

第二步:数据清洗

print("=== 洗前 ===")
print(f"缺失值:\n{df.isnull().sum()}")
print(f"quantity<0: {(df['quantity'] < 0).sum()} 行")
print(f"空城市: {(df['city'] == '').sum()} 行")

# 1. city 填"未知"
df["city"] = df["city"].replace("", "未知")

# 2. total_amount 用单价×数量回填
mask = df["total_amount"].isna()
df.loc[mask, "total_amount"] = df.loc[mask, "quantity"] * df.loc[mask, "unit_price"]

# 3. 异常 quantity 剔除
df = df[df["quantity"] > 0]

print(f"\n=== 洗后 ===")
print(f"缺失值: {df.isnull().sum().sum()}")
print(f"数据量: {len(df)} 行")

第三步:初步概览

print(f"总销售额: {df['total_amount'].sum():,.0f} 元")
print(f"总订单数: {len(df)}")
print(f"客单价: {df['total_amount'].mean():.0f} 元")
print(f"总销量: {df['quantity'].sum()} 件")

第四步:多维度分析

fig, axes = plt.subplots(2, 3, figsize=(18, 12))

# 1. 月度销售趋势
df["month"] = df["date"].dt.to_period("M")
monthly = df.groupby("month")["total_amount"].sum()
axes[0, 0].plot(monthly.index.astype(str), monthly.values, marker="o", color="#378ADD")
axes[0, 0].set_title("月度销售额趋势")
axes[0, 0].tick_params(axis="x", rotation=45)
axes[0, 0].set_ylabel("销售额(元)")

# 2. 产品销售额排行
product_sales = df.groupby("product")["total_amount"].sum().sort_values()
axes[0, 1].barh(product_sales.index, product_sales.values, color="#378ADD")
axes[0, 1].set_title("各产品销售额")

# 3. 渠道占比
channel_data = df["channel"].value_counts()
axes[0, 2].pie(channel_data.values, labels=channel_data.index, autopct="%1.1f%%",
               colors=["#378ADD", "#D85A30"])
axes[0, 2].set_title("订单渠道分布")

# 4. 城市销售额 Top 5
city_sales = df.groupby("city")["total_amount"].sum().nlargest(5)
axes[1, 0].bar(city_sales.index, city_sales.values, color=["#378ADD", "#D85A30", "#1D9E75", "#BA7517", "#888780"])
axes[1, 0].set_title("销售额Top5城市")

# 5. 各产品客单价
avg_price = df.groupby("product")["total_amount"].mean().sort_values()
axes[1, 1].barh(avg_price.index, avg_price.values, color="#1D9E75")
axes[1, 1].set_title("各产品客单价(元)")

# 6. 月度订单量
monthly_orders = df.groupby("month")["order_id"].count()
axes[1, 2].bar(monthly_orders.index.astype(str), monthly_orders.values, color="#BA7517")
axes[1, 2].set_title("月度订单量")
axes[1, 2].tick_params(axis="x", rotation=45)

plt.suptitle("2025年度电商销售分析报告", fontsize=18, fontweight="bold", y=1.02)
plt.tight_layout()
plt.savefig("ecommerce_report.png", dpi=150, bbox_inches="tight")
plt.show()

第五步:RFM 分析——找出高价值客户

# 模拟用户维度(假设每个订单有用户ID)
df["user_id"] = np.random.choice(range(1, 501), len(df))
now = pd.Timestamp("2026-01-01")

rfm = df.groupby("user_id").agg(
    recency=("date", lambda x: (now - x.max()).days),   # 最近一次购买距今天数
    frequency=("order_id", "count"),                      # 购买次数
    monetary=("total_amount", "sum")                      # 消费总额
)

# 评分(1-4分,4=最好)
rfm["R_score"] = pd.qcut(rfm["recency"], 4, labels=[4, 3, 2, 1])  # 天数少=分数高
rfm["F_score"] = pd.qcut(rfm["frequency"].rank(method="first"), 4, labels=[1, 2, 3, 4])
rfm["M_score"] = pd.qcut(rfm["monetary"], 4, labels=[1, 2, 3, 4])

rfm["RFM_score"] = (rfm["R_score"].astype(str) + 
                    rfm["F_score"].astype(str) + 
                    rfm["M_score"].astype(str))

# 用户分层
def segment(score):
    if score in ["444", "443", "434", "344"]:
        return "重要价值客户"
    elif score[1] == "4":
        return "重要发展客户"
    elif score[0] == "4":
        return "重要保持客户"
    elif score[2] == "4":
        return "重要挽留客户"
    else:
        return "一般客户"

rfm["segment"] = rfm["RFM_score"].apply(segment)
print("\n=== 用户分层 ===")
print(rfm["segment"].value_counts())

print(f"\n重要价值客户消费: {rfm[rfm['segment']=='重要价值客户']['monetary'].sum():,.0f} 元")

第六步:输出分析结论

print("""
=== 核心结论 ===

1. 销售趋势:全年销售额呈现 [上升/稳定] 态势,[11月/12月] 为峰值
2. 拳头产品:{top_product} 贡献了 {pct}% 的销售额
3. 渠道特征:线上订单占比 {online_pct}%,且客单价高于线下
4. 城市表现:Top 5 城市贡献了 {city_pct}% 的销售额
5. 用户价值:{vip_count}% 的重要价值客户贡献了 {vip_pct}% 的销售额
""".format(
    top_product=product_sales.index[-1],
    pct=f"{product_sales.max() / product_sales.sum() * 100:.1f}",
    online_pct=f"{channel_data['线上'] / len(df) * 100:.1f}",
    city_pct=f"{city_sales.sum() / df['total_amount'].sum() * 100:.1f}",
    vip_count=f"{(rfm['segment']=='重要价值客户').sum() / len(rfm) * 100:.1f}",
    vip_pct=f"{rfm[rfm['segment']=='重要价值客户']['monetary'].sum() / rfm['monetary'].sum() * 100:.1f}",
))

写在最后

这个案例覆盖了数据清洗、多维度分析、RFM 模型、可视化报告——一条完整的数据分析链路。

关键不是记住代码,而是理解分析思路:先看全貌 → 拆维度 → 找规律 → 出结论

下一篇是最后一个实战——分析招聘数据,用 Python 看看什么岗位最有"钱"途。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐