Python数据可视化项目实战:基于Matplotlib与Pyecharts的案例

慢慢来
慢慢来
发布时间:2026-10-25| 4人浏览过
原创

在企业级数据分析与业务呈现中,数据可视化承担着从“清洗后数据”到“辅助业务决策”的最后一公里转化任务。面对多样化的交付需求,开发者通常需要在两类技术路线中进行取舍:一种是以 Matplotlib 为代表的底层栅格/矢量渲染引擎,主要面向学术报告、离线印刷品及高定制化静态图表;另一种是以 Pyecharts 为代表的现代 Web 交互图表库,擅长通过 JSON 协议驱动前端 Echarts 引擎,交付高信息密度的交互式仪表盘与动态钻取页面。本文通过一个端到端的综合电商经营分析案例,完整演示从环境搭建、数据建模到两套渲染体系的具体落地流程与工程规范。

一、Matplotlib 与 Pyecharts 技术定位与渲染架构对比

在立项之初明确工具链的运行边界,是避免后期工程重构的关键。Matplotlib 与 Pyecharts 在运行机制、产物形态与使用场景上存在本质差异。

Python数据可视化项目实战:基于Matplotlib与Pyecharts的案例
图1:Matplotlib 与 Pyecharts 技术定位与底层流水线架构对比

从架构可见,Matplotlib 是典型的工作流终点,Python 计算完成后直接生成图形文件;而 Pyecharts 则充当了 Python 数据逻辑与浏览器渲染引擎之间的“协议转译器”,图表的真正生命周期发生在客户端浏览器中。

二、可视化项目标准开发与交付流程

实际生产项目中,可视化图表并不是孤立编写的几行绘图代码,而是涉及“业务问题提炼 → 数据规整转换 → 图表选型与排版 → 样式约束与校准 → 多格式分发交付”五个连贯环节的标准工程过程。

Python数据可视化项目实战:基于Matplotlib与Pyecharts的案例
图2:企业级数据可视化项目标准开发与交付流程

三、开发环境配置与公共测试数据建模

为了保证代码的可重复运行与依赖隔离,请在虚拟环境中安装当前稳定版本的核心依赖库:

pip install matplotlib>=3.8.0 pyecharts>=2.0.4 pandas>=2.1.0 numpy>=1.26.0

本项目以某新零售电商品牌“2024年第一季度全渠道销售运营分析”为业务背景。数据涵盖四大核心维度:

  • 时间趋势维度:2024年1月至3月每周的销售额(万元)与净利润率(%)。
  • 品类分布维度:数码家电、服饰鞋包、生鲜食品、居家生活、美妆个护五大品类的销售占比。
  • 漏斗转化维度:全站“商品曝光 → 详情页浏览 → 加购 → 提交订单 → 支付成功”五级转化漏斗。
  • 区域渗透维度:各主力省份的销售额分段分布。

下面编写数据准备模块 data_loader.py,生成标准 DataFrame 与结构化字典供后续渲染模块调用:

import pandas as pd
import numpy as np

def generate_retail_dataset():
    """
    构造零售电商全流程清洗后分析数据集
    """
    # 1. 周销售趋势数据
    weeks = [f"第{i:02d}周" for i in range(1, 13)]
    np.random.seed(42)
    sales_amount = [120, 135, 128, 142, 160, 175, 190, 185, 210, 225, 240, 260] # 万元
    profit_margin = [18.2, 17.5, 19.0, 18.8, 16.5, 15.8, 16.2, 17.0, 15.5, 14.8, 15.2, 14.5] # %
    df_trend = pd.DataFrame({
        "week": weeks,
        "sales": sales_amount,
        "margin": profit_margin
    })

    # 2. 品类结构分布
    categories = ["数码家电", "服饰鞋包", "生鲜食品", "居家生活", "美妆个护"]
    category_sales = [820, 540, 380, 290, 210] # 季度汇总销售额(万元)
    category_ratios = [round(v / sum(category_sales) * 100, 2) for v in category_sales]
    df_category = pd.DataFrame({
        "category": categories,
        "sales": category_sales,
        "ratio": category_ratios
    })

    # 3. 电商转化漏斗
    funnel_steps = ["商品曝光", "详情浏览", "加入购物车", "提交订单", "支付成功"]
    funnel_counts = [1000000, 450000, 180000, 85000, 68000] # 人次
    funnel_rates = [100.0]
    for i in range(1, len(funnel_counts)):
        funnel_rates.append(round(funnel_counts[i] / funnel_counts[0] * 100, 2))
    df_funnel = pd.DataFrame({
        "step": funnel_steps,
        "count": funnel_counts,
        "rate": funnel_rates
    })

    return {
        "trend": df_trend,
        "category": df_category,
        "funnel": df_funnel
    }

if __name__ == "__main__":
    dataset = generate_retail_dataset()
    print("数据集构建成功,趋势数据前3行:")
    print(dataset["trend"].head(3))

四、Matplotlib 静态出版级多子图报告实战

Matplotlib 最强项在于面向对象的对象树结构体系(Figure → Axes → Axis/Artist)。在编写生产级代码时,应始终避免使用 plt.plot() 这类隐式状态机接口,改用显式创建 fig, ax = plt.subplots() 模式,确保所有坐标轴和标注都具备确定的指针引用。

Python数据可视化项目实战:基于Matplotlib与Pyecharts的案例
图3:Matplotlib 对象树模型与双 Y 轴/环形子图空间层级结构

完整实战代码:生成专业分析看板

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from data_loader import generate_retail_dataset

# 1. 中文字体与显示安全配置
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False  # 保证负号正常显示
plt.rcParams['figure.dpi'] = 300          # 出版级高分辨率

def build_matplotlib_report():
    data = generate_retail_dataset()
    df_trend = data["trend"]
    df_cat = data["category"]

    # 工程标准配色体系
    COLOR_PRIMARY = "#345E82"   # 工程蓝
    COLOR_ACCENT = "#AD8060"    # 铜棕强调色
    COLOR_BG = "#F8FAFC"        # 画布底色
    COLOR_PALETTE = ["#345E82", "#AD8060", "#4A7C9D", "#D9A779", "#8CA8BE"]

    # 创建双子图画布
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6), facecolor=COLOR_BG)
    fig.suptitle("2024年Q1零售电商经营核心指标复盘报告", fontsize=18, fontweight="bold", color="#1E293B", y=0.98)

    # ------------------ 左图:双 Y 轴复合时序分析 ------------------
    ax1.set_facecolor("#FFFFFF")
    bars = ax1.bar(
        df_trend["week"], 
        df_trend["sales"], 
        color=COLOR_PRIMARY, 
        alpha=0.88, 
        width=0.55, 
        label="周销售额 (万元)"
    )
    ax1.set_ylabel("周销售额 (万元)", fontsize=12, fontweight="bold", color=COLOR_PRIMARY)
    ax1.set_ylim(0, 300)
    ax1.tick_params(axis="y", labelcolor=COLOR_PRIMARY)
    ax1.tick_params(axis="x", rotation=40, labelsize=10)
    ax1.grid(axis="y", linestyle="--", alpha=0.3, color="#CBD5E1")

    # 在柱顶标注数值
    for bar in bars:
        h = bar.get_height()
        ax1.annotate(f"{int(h)}",
                     xy=(bar.get_x() + bar.get_width() / 2, h),
                     xytext=(0, 4), textcoords="offset points",
                     ha="center", va="bottom", fontsize=9, color="#1E293B")

    # 实例化次坐标轴
    ax1_twin = ax1.twinx()
    line = ax1_twin.plot(
        df_trend["week"], 
        df_trend["margin"], 
        color=COLOR_ACCENT, 
        linewidth=2.5, 
        marker="o", 
        markersize=6, 
        label="净利润率 (%)"
    )
    ax1_twin.set_ylabel("净利润率 (%)", fontsize=12, fontweight="bold", color=COLOR_ACCENT)
    ax1_twin.set_ylim(10, 25)
    ax1_twin.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=100, decimals=1))
    ax1_twin.tick_params(axis="y", labelcolor=COLOR_ACCENT)

    # 合并两个坐标系的图例说明
    lines_1, labels_1 = ax1.get_legend_handles_labels()
    lines_2, labels_2 = ax1_twin.get_legend_handles_labels()
    ax1.legend(lines_1 + lines_2, labels_1 + labels_2, loc="upper left", framealpha=0.9)
    ax1.set_title("周度销售体量与利润率走势 (规模增长与利润承压)", fontsize=13, fontweight="bold", pad=12)

    # ------------------ 右图:品类贡献环形分布 ------------------
    ax2.set_facecolor("#FFFFFF")
    wedges, texts, autotexts = ax2.pie(
        df_cat["sales"],
        labels=df_cat["category"],
        autopct="%1.1f%%",
        startangle=140,
        colors=COLOR_PALETTE,
        pctdistance=0.75,
        textprops=dict(color="#1E293B", fontsize=11),
        wedgeprops=dict(width=0.45, edgecolor="#FFFFFF", linewidth=2)  # 挖空形成环形
    )
    for at in autotexts:
        at.set_fontsize(10)
        at.set_weight("bold")
        at.set_color("#FFFFFF")

    ax2.set_title("Q1 品类销售规模结构分布", fontsize=13, fontweight="bold", pad=12)

    # 自动规整并输出
    plt.tight_layout()
    output_png = "report_matplotlib_q1.png"
    plt.savefig(output_png, dpi=300, bbox_inches="tight", facecolor=COLOR_BG)
    plt.close()
    print(f"Matplotlib 静态高质量报告已成功保存至: {output_png}")

if __name__ == "__main__":
    build_matplotlib_report()
工程避坑提醒: 在 Linux 无图形界面(Headless)服务器上定时批量跑 Matplotlib 脚本时,必须在导入 matplotlib.pyplot 前强制设置无界面的后端驱动:import matplotlib; matplotlib.use('Agg')。否则代码在尝试初始化 X11 或 Wayland 显示连接时会直接抛出 TclError: no display name and no $DISPLAY environment variable 致命异常。

五、Pyecharts 交互式仪表盘与联动实战

与静态报告追求绝对像素对齐不同,Web 交互式大屏需要提供:跨指标鼠标悬停详情(Tooltip)、多品类动态开闭(Legend Filter)、时间轴滑块缩放(DataZoom)以及流式漏斗排布。Pyecharts 2.x 版本全面采用链式调用与强类型配置项(opts),将配置语义直接对标 Apache Echarts 规范。

1. 交互漏斗图与双指标联动柱折图

以下代码构建一套可交互的独立 HTML 仪表盘,利用 Page(layout=Page.DraggablePageLayout) 或 Grid 将漏斗转化模型与销售时序模型组合排布:

from pyecharts.charts import Bar, Line, Funnel, Grid
from pyecharts import options as opts
from data_loader import generate_retail_dataset

def build_pyecharts_dashboard():
    data = generate_retail_dataset()
    df_trend = data["trend"]
    df_funnel = data["funnel"]

    # 1. 构造主时序双 Y 轴柱折图
    bar = (
        Bar(init_opts=opts.InitOpts(theme="white", width="100%", height="420px"))
        .add_xaxis(df_trend["week"].tolist())
        .add_yaxis(
            "周销售额 (万元)",
            df_trend["sales"].tolist(),
            yaxis_index=0,
            color="#345E82",
            label_opts=opts.LabelOpts(is_show=False)
        )
        .extend_axis(
            yaxis=opts.AxisOpts(
                name="利润率 (%)",
                type_="value",
                min_=10,
                max_=25,
                interval=5,
                axislabel_opts=opts.LabelOpts(formatter="{value} %"),
                splitline_opts=opts.SplitLineOpts(is_show=False)
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="销售走势与利润率波动交互分析", subtitle="支持鼠标悬停、区域缩放与数据视图下钻"),
            tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
            legend_opts=opts.LegendOpts(pos_top="5%", pos_right="10%"),
            yaxis_opts=opts.AxisOpts(
                name="销售额 (万元)",
                min_=0,
                max_=300,
                splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts(opacity=0.3))
            ),
            # 引入交互式缩放滑动条
            datazoom_opts=[
                opts.DataZoomOpts(type_="slider", range_start=0, range_end=100, pos_bottom="2%"),
                opts.DataZoomOpts(type_="inside")
            ]
        )
    )

    line = (
        Line()
        .add_xaxis(df_trend["week"].tolist())
        .add_yaxis(
            "净利润率 (%)",
            df_trend["margin"].tolist(),
            yaxis_index=1,
            color="#AD8060",
            symbol="circle",
            symbol_size=7,
            linestyle_opts=opts.LineStyleOpts(width=3),
            label_opts=opts.LabelOpts(is_show=True, formatter="{c}%")
        )
    )
    # 将折线图合并重叠渲染在柱状图的主体坐标系中
    trend_combo = bar.overlap(line)

    # 2. 构造转化漏斗图
    funnel_pairs = [list(z) for z in zip(df_funnel["step"], df_funnel["rate"])]
    funnel = (
        Funnel(init_opts=opts.InitOpts(theme="white", width="100%", height="420px"))
        .add(
            series_name="全链路漏斗转化",
            data_pair=funnel_pairs,
            gap=2,
            tooltip_opts=opts.TooltipOpts(formatter="{a} <br/>{b} : {c}% 留存率"),
            label_opts=opts.LabelOpts(position="inside", formatter="{b}: {c}%")
        )
        .set_colors(["#345E82", "#4A7C9D", "#6F9BB9", "#AD8060", "#D9A779"])
        .set_global_opts(
            title_opts=opts.TitleOpts(title="全站用户转化链路留存分析", pos_left="center"),
            legend_opts=opts.LegendOpts(orient="vertical", pos_left="left", pos_top="middle")
        )
    )

    # 3. 页面聚合与持久化导出
    # 在生产中可使用 Grid 布局将两者紧凑整合在单页内,此处分别生成或组合导出
    trend_combo.render("dashboard_trend.html")
    funnel.render("dashboard_funnel.html")
    print("Pyecharts 交互式图表已成功生成: dashboard_trend.html, dashboard_funnel.html")

if __name__ == "__main__":
    build_pyecharts_dashboard()
Pyecharts 资源加载离线化配置: 默认情况下,Pyecharts 生成的 HTML 页面会从外部公共 CDN(如 assets.pyecharts.org)拉取 echarts.min.js 等前端脚本。在企业内网断网环境、隔离容器或对合规要求极高的私有云环境中,页面可能出现无法联网而白屏的问题。应通过 CurrentConfig.ONLINE_HOST = "/static/assets/" 将 JS 静态资源重定向为本地相对路径或企业内部 Nginx 静态站点。

六、技术选型矩阵与核心指标总结

为了在实际团队开发中规范代码资产、避免“各写一套、格式冲突”,以下给出两套工具在工程实施各维度的定性与定量选型对照:

Python数据可视化项目实战:基于Matplotlib与Pyecharts的案例
图4:Matplotlib 与 Pyecharts 技术选型综合决策矩阵与实施建议

核心检查清单 (Go-Live Checklist)

  1. 单位量纲标注:所有坐标轴刻度及标注文字必须明确说明数值单位(万元、百分比、件数),避免业务误读。
  2. 配色一致性:全局严控配色不超过 5 种,主色调与强调色保持 3:1 的视觉比重,杜绝彩虹色混杂。
  3. 自动化容错:在批处理脚本中显式调用 plt.close(fig) 释放内存,避免常驻进程发生内存泄漏;确保 Pyecharts 离线依赖资源路径可解析。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。