尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python pyecharts 实战:手把手教你绘制专业帕累托图

Python pyecharts 实战:手把手教你绘制专业帕累托图 1. 从数据报表到决策洞察为什么我们需要帕累托图如果你经常和数据打交道无论是产品运营、质量分析还是项目管理大概率都听过“二八法则”——80%的问题往往由20%的原因造成80%的销售额可能来自20%的客户。这个道理听起来简单但如何在一堆杂乱的数据中直观地找出那关键的“20%”并说服你的同事或老板呢这时候帕累托图Pareto Chart就派上用场了。帕累托图本质上是一个组合图表它将柱状图和折线图叠加在一起。柱状图按降序排列展示各个类别的频数或金额折线图则是这些类别的累积百分比。图表上通常会画一条80%的参考线。一眼望去你就能看到哪些类别是“头部问题”它们累积贡献了多少比例。这比单纯看一个排序的表格要直观得多因为它把“重要性排序”和“累积影响”两个维度同时呈现了出来是进行问题优先级排序、资源聚焦分配的绝佳可视化工具。过去制作这样的专业图表可能需要依赖Excel的复杂操作或者更专业的BI工具。但对于数据分析师和开发者来说如果能在Python的数据分析流程中直接生成高质量、可交互的帕累托图无疑会极大提升报告效率和自动化水平。pyecharts这个基于ECharts的Python可视化库以其丰富的图表类型、优雅的交互效果和灵活的配置选项成为了一个非常不错的选择。它生成的图表是网页格式可以无缝嵌入到Web应用或离线报告中视觉效果和专业度都相当出色。今天我就结合一次实际的数据分析需求来手把手带你用pyecharts从零绘制一个专业的帕累托图。我们会从数据模拟与准备开始一步步拆解图表构建的每一个环节并深入探讨那些官方文档可能不会细说但在实际应用中至关重要的细节和“坑点”。2. 环境准备与数据模拟构建一个贴近实战的分析场景在开始画图之前我们得先把“舞台”搭好。这里包括两件事确保你的Python环境里有必要的工具以及准备一份用于演示的、贴近真实业务逻辑的数据。2.1 安装与导入核心库首先你需要安装pyecharts。我强烈建议使用最新版本本文基于1.x版本其API设计与早期版本有较大不同更清晰易用。通过pip安装非常简单pip install pyecharts如果你需要将图表保存为静态图片比如PNG格式以便插入PPT或Word还需要安装额外的渲染器。pyecharts本身主要生成HTML保存为图片需要依赖selenium或phantomjs配置起来稍显麻烦。一个更便捷的选择是安装pyecharts-snapshot插件并配合phantomjspip install pyecharts-snapshot # 然后需要下载 phantomjs 的可执行文件并将其路径加入系统环境变量。不过对于大多数分析报告场景生成一个独立的、可交互的HTML文件已经足够我们本次就以生成HTML为例。接下来在Python脚本或Jupyter Notebook中我们需要导入必要的模块import pandas as pd import numpy as np from pyecharts import options as opts from pyecharts.charts import Bar, Line from pyecharts.commons.utils import JsCode这里解释一下为什么这样导入pandas和numpy是数据处理的基础我们用来构造和整理数据。从pyecharts.charts导入Bar和Line因为帕累托图是两者的组合。opts模块包含了所有图表配置项用于精细化控制图表的每一个视觉元素。JsCode是一个非常有用的工具它允许我们注入自定义的JavaScript代码到图表中实现一些高级的、预设配置无法满足的效果后面我们会用到它来格式化坐标轴标签。2.2. 模拟一份产品缺陷分析数据为了演示我们虚构一个场景某App上线后通过用户反馈和测试收集到了一周内各类缺陷的报错次数。我们的目标是找出最影响用户体验的“关键少数”缺陷类型。# 模拟数据缺陷类型及其发生次数 data { ‘缺陷类型‘: [‘界面卡顿‘, ‘支付失败‘, ‘图片加载慢‘, ‘消息推送延迟‘, ‘注册流程复杂‘, ‘视频播放卡顿‘, ‘搜索无结果‘, ‘账号登录异常‘, ‘字体显示模糊‘, ‘夜间模式闪退‘], ‘发生次数‘: [156, 89, 72, 64, 58, 47, 35, 28, 19, 12] } # 转换为DataFrame df pd.DataFrame(data) # 按‘发生次数‘降序排列这是绘制帕累托图的第一步 df_sorted df.sort_values(by‘发生次数‘, ascendingFalse).reset_index(dropTrue) print(df_sorted)运行后你会得到一份已经排序好的数据缺陷类型 发生次数 0 界面卡顿 156 1 支付失败 89 2 图片加载慢 72 3 消息推送延迟 64 4 注册流程复杂 58 5 视频播放卡顿 47 6 搜索无结果 35 7 账号登录异常 28 8 字体显示模糊 19 9 夜间模式闪退 12关键点解析为什么必须先排序帕累托图的柱状图部分要求数据按照度量值这里是发生次数从大到小排列这是其核心逻辑——让最重要的项排在左边。如果数据是乱序的那么累积百分比折线将失去意义无法清晰展示“少数关键因素”的累积效应。2.3. 计算累积百分比这是绘制折线图的数据基础。累积百分比表示到当前缺陷类型为止所有缺陷发生次数占总次数的比例。# 计算总次数 total df_sorted[‘发生次数‘].sum() # 计算累积次数 df_sorted[‘累积次数‘] df_sorted[‘发生次数‘].cumsum() # 计算累积百分比 df_sorted[‘累积百分比‘] df_sorted[‘累积次数‘] / total * 100 # 格式化一下保留两位小数方便查看 df_sorted[‘累积百分比‘] df_sorted[‘累积百分比‘].round(2) print(df_sorted[[‘缺陷类型‘, ‘发生次数‘, ‘累积百分比‘]])现在数据准备就绪了。我们有了类别缺陷类型、柱状图数据发生次数和折线图数据累积百分比。接下来进入核心的图表构建环节。3. 核心图表构建组合Bar与Line的技法与陷阱pyecharts绘制组合图表的精髓在于使用overlap方法或者在一个Grid布局中叠加。对于帕累托图这种X轴完全共享的图表使用overlap更为简单直接。我们的思路是先绘制柱状图Bar再在其基础上叠加折线图Line。3.1. 绘制基础柱状图首先我们初始化一个柱状图对象并设置基本的X轴和Y轴数据。# 初始化柱状图 bar ( Bar(init_optsopts.InitOpts(width“900px“, height“500px“)) # 设置画布大小 .add_xaxis(df_sorted[‘缺陷类型‘].tolist()) # X轴缺陷类型 .add_yaxis( series_name“发生次数“, # 系列名称会显示在图例中 y_axisdf_sorted[‘发生次数‘].tolist(), # Y轴发生次数 category_gap“50%“, # 柱子之间的间隙设为50%看起来比较舒适 color“#5470c6“, # 自定义柱子颜色ECharts经典蓝色 ) .set_global_opts( title_optsopts.TitleOpts(title“产品缺陷帕累托分析“, subtitle“基于发生次数的优先级排序“), tooltip_optsopts.TooltipOpts( trigger“axis“, # 触发方式坐标轴触发鼠标移到轴上任意位置都会显示提示框 axis_pointer_type“shadow“ # 坐标轴指示器类型为阴影效果更好看 ), ) )经验之谈一关于category_gap。这个参数控制同一系列中不同柱子之间的间距。如果设置得太小比如“0%”柱子会挤在一起影响阅读设置得太大又会显得稀疏。对于帕累托图这种需要清晰区分每个类别的图表“40%”到“60%”是一个比较合适的范围。你可以根据类别的多少进行调整。经验之谈二关于tooltip的trigger。这里设置为“axis“有一个巨大好处当鼠标在图表上横向移动时会有一条竖线跟随并同时显示该X坐标位置下所有系列柱子和折线的具体数值。这对于对比某个类别下的原始次数和累积百分比非常方便。如果设为默认的“item“则只会显示鼠标悬停的那个具体图形元素如单个柱子的信息。3.2. 绘制累积百分比折线图接下来我们在同一个坐标系上添加折线图。这里有几个关键配置Y轴对齐折线图的数据百分比和柱状图数据次数量纲不同必须使用独立的Y轴。折线样式需要将其与柱状图明显区分通常使用红色并加上数据点标记。标签格式化我们希望折线图的数据点标签显示为“xx%”的格式。# 初始化折线图 line ( Line() .add_xaxis(df_sorted[‘缺陷类型‘].tolist()) # 共享同一个X轴 .add_yaxis( series_name“累积百分比“, y_axisdf_sorted[‘累积百分比‘].tolist(), yaxis_index1, # 关键指定使用第二个Y轴索引为1 color“#d14a61“, # 红色与蓝色柱子形成对比 label_optsopts.LabelOpts( is_showTrue, # 显示数据标签 formatterJsCode(“function(params){return params.value ‘%‘;}“) # 使用JS代码格式化标签为百分比 ), linestyle_optsopts.LineStyleOpts(width3), # 设置线宽 symbol“circle“, # 数据点标记为圆形 symbol_size8, # 标记大小 ) )核心细节解析yaxis_index1。这是实现双Y轴的核心。在pyecharts中第一个Y轴索引0是默认的、为柱状图服务的左侧Y轴。通过设置yaxis_index1我们告诉折线图“你的数据应该参考第二个Y轴来绘制。” 接下来我们就需要创建并配置这第二个Y轴。3.3. 组合图表与配置双Y轴现在将折线图叠加到柱状图上并完成全局的坐标轴配置。# 将折线图叠加到柱状图上 pareto_chart bar.overlap(line) # 配置全局选项重点是第二个Y轴 pareto_chart.set_global_opts( # 配置第一个Y轴左侧用于柱状图 yaxis_optsopts.AxisOpts( name“发生次数“, type_“value“, axislabel_optsopts.LabelOpts(formatter“{value} 次“), # 格式化标签 ), # 配置第二个Y轴右侧用于折线图 yaxis_optsopts.AxisOpts( name“累积百分比“, type_“value“, position“right“, # 位置在右侧 axislabel_optsopts.LabelOpts(formatter“{value}%“), # 格式化标签为百分比 max_100, # 最大值固定为100% interval20, # 刻度间隔为20% splitline_optsopts.SplitLineOpts( # 设置网格线便于观察 is_showTrue, linestyle_optsopts.LineStyleOpts(type_“dashed“, opacity0.5) ), ), # 配置X轴 xaxis_optsopts.AxisOpts( axislabel_optsopts.LabelOpts(rotate-30), # 标签旋转-30度防止重叠 name“缺陷类型“, ), # 图例配置 legend_optsopts.LegendOpts(pos_top“10%“), # 将图例放在顶部避免遮挡标题 # 工具箱提供保存图片等功能 toolbox_optsopts.ToolboxOpts( is_showTrue, feature{ “saveAsImage“: {}, # 保存为图片 “dataView“: {“readOnly“: True}, # 数据视图 } ), )踩坑记录Y轴配置的覆盖问题。set_global_opts中的yaxis_opts默认只配置第一个Y轴。当你需要配置第二个Y轴时必须像上面代码一样传入一个opts.AxisOpts列表。第一个元素对应索引0的Y轴第二个元素对应索引1的Y轴。如果只传一个配置对象那么第二个Y轴会使用默认设置可能导致刻度不对齐、标签格式错误等问题。实用技巧max_100和interval20。对于累积百分比折线将其Y轴最大值固定为100%并以20%为间隔划分网格线这是一个行业惯例。它使得80%的参考线我们下一步会添加能清晰地落在网格上让图表更易读。4. 画龙点睛添加80%参考线与高级视觉优化一个专业的帕累托图80%参考线几乎是标配。这条线能帮助读者快速定位“关键少数”的边界。在pyecharts中我们可以通过MarkLine组件轻松实现。4.1. 为折线图添加80%参考线我们直接在折线图系列上添加一条贯穿整个图表的水平标记线。# 在之前的line配置中扩展add_yaxis的配置加入markline line ( Line() .add_xaxis(df_sorted[‘缺陷类型‘].tolist()) .add_yaxis( series_name“累积百分比“, y_axisdf_sorted[‘累积百分比‘].tolist(), yaxis_index1, color“#d14a61“, label_optsopts.LabelOpts(is_showTrue, formatterJsCode(“function(params){return params.value ‘%‘;}“)), linestyle_optsopts.LineStyleOpts(width3), symbol“circle“, symbol_size8, # 添加标记线 markline_optsopts.MarkLineOpts( data[opts.MarkLineItem(y80, name“80%参考线“)], # 在Y轴值为80的位置画线 linestyle_optsopts.LineStyleOpts(type_“dashed“, color“#999“, width2), # 虚线灰色 label_optsopts.LabelOpts( # 标签配置 position“insideEndTop“, # 标签在线段内部末端顶部 formatter“{b}“, # 显示数据项的名称即‘80%参考线‘ color“#333“ ) ) ) )重要提示MarkLine是添加在Line系列的add_yaxis方法里的而不是在全局配置中。这意味着这条线是折线图的一部分其Y坐标值遵循折线图所在的Y轴即我们设置的第二个Y轴索引1。因此y80表示的是80%的位置完全正确。4.2. 优化数据标签与提示框为了让图表信息更清晰我们可以进一步优化提示框Tooltip的显示内容。默认的提示框可能会同时显示“发生次数”和“累积百分比”但格式是数字。我们可以自定义其格式使其更友好。# 更新全局配置中的tooltip_opts pareto_chart.set_global_opts( # ... 保留之前所有的yaxis_opts, xaxis_opts等配置 ... tooltip_optsopts.TooltipOpts( trigger“axis“, axis_pointer_type“shadow“, # 自定义格式化函数 formatterJsCode(“““ function (params) { let result params[0].name ‘br/‘; for (let i0; iparams.length; i) { if (params[i].seriesName ‘发生次数‘) { result params[i].marker params[i].seriesName ‘: ‘ params[i].value ‘ 次br/‘; } else if (params[i].seriesName ‘累积百分比‘) { result params[i].marker params[i].seriesName ‘: ‘ params[i].value.toFixed(1) ‘%br/‘; } } return result; } “““) ), )这段JavaScript代码做了以下几件事获取当前X轴坐标即缺陷类型作为标题。遍历所有系列params数组包含柱子和折线的数据点。根据系列名称分别格式化其值次数后面加“次”百分比保留一位小数并加“%”。使用br/进行换行使显示更整齐。4.3. 渲染与保存图表最后将图表渲染为HTML文件这样就可以在浏览器中打开并交互了。# 渲染图表到HTML文件 pareto_chart.render(“defect_pareto_analysis.html“)打开生成的defect_pareto_analysis.html文件你将看到一个完整的、交互式的帕累托图。鼠标悬停可以查看详细数据可以点击图例隐藏/显示某个系列还可以利用工具箱保存为图片。5. 结果解读与实战进阶从图表到行动方案现在让我们来解读一下我们亲手绘制的这张帕累托图。直观观察柱状图从左到右依次降低清晰地展示了“界面卡顿”是发生次数最多的缺陷。折线图快速上升在前几个类别就达到了很高的累积百分比。关键分析找到累积百分比折线首次穿过80%参考线的点。从我们的模拟数据图上看这个点大约在“注册流程复杂”和“视频播放卡顿”之间。这意味着排名前五的缺陷界面卡顿、支付失败、图片加载慢、消息推送延迟、注册流程复杂其累积发生次数已经超过了总次数的80%。这五类缺陷就是我们应当优先投入资源进行修复的“关键少数”。行动建议立即聚焦开发团队应优先解决“界面卡顿”和“支付失败”这两个头部问题它们贡献了最大的问题量。制定计划针对前五类缺陷制定详细的排查和修复计划。持续监控在修复之后应重新收集数据绘制新的帕累托图以验证修复效果并发现新的“关键少数”。5.1. 常见问题与进阶处理在实际项目中你可能会遇到一些特殊情况需要调整我们的基础代码情况一数据类别过多X轴标签重叠当缺陷类型超过15个时即使旋转标签也会显得拥挤。解决方案是使用X轴的axislabel间隔显示或者将过长的类别名截断。xaxis_optsopts.AxisOpts( axislabel_optsopts.LabelOpts( rotate-45, interval0, # 0表示显示所有标签可以设为1隔一个显示一个 formatterJsCode(“““ function(value) { // 如果标签名太长截取前6个字符并加... if (value.length 6) { return value.substr(0, 6) ‘...‘; } else { return value; } } “““) ), )情况二数据量纲差异巨大如果“发生次数”的数值很大如几万而“累积百分比”是小数会导致柱状图几乎顶到天花板折线图却紧贴底部。这时需要对双Y轴的刻度进行更精细的配置确保两个系列都能在图表中清晰展示。通常pyecharts会自动计算合适的刻度范围但如果自动效果不佳可以手动指定min_和max_参数。情况三需要动态数据或集成到Web应用pyecharts生成的HTML文件是独立的。如果你需要将图表集成到Flask、Django等Web框架中可以使用render_embed()方法生成不包含完整HTML结构的图表组件然后将其嵌入到你的模板中。对于动态数据你需要在后端准备好数据调用相同的绘图逻辑生成图表配置然后传递给前端渲染。5.2. 封装成可复用的函数为了提高效率我们可以将整个绘图过程封装成一个函数以后只需传入数据和少量参数即可生成帕累托图。def create_pareto_chart(categories, values, title“帕累托图“, xaxis_name“类别“, yaxis_name“数值“): “““ 创建帕累托图 Args: categories: list, 类别列表 values: list, 数值列表与categories一一对应 title: str, 图表标题 xaxis_name: str, X轴名称 yaxis_name: str, 主Y轴柱状图名称 Returns: pyecharts.charts.composite_charts.Overlap: 组合图表对象 “““ # 1. 数据准备 df pd.DataFrame({‘category‘: categories, ‘value‘: values}) df_sorted df.sort_values(by‘value‘, ascendingFalse).reset_index(dropTrue) total df_sorted[‘value‘].sum() df_sorted[‘cum_pct‘] (df_sorted[‘value‘].cumsum() / total * 100).round(2) # 2. 绘制柱状图 bar ( Bar(init_optsopts.InitOpts(width“1000px“, height“600px“)) .add_xaxis(df_sorted[‘category‘].tolist()) .add_yaxis(yaxis_name, df_sorted[‘value‘].tolist(), color“#5470c6“, gap“50%“) .set_global_opts( title_optsopts.TitleOpts(titletitle), xaxis_optsopts.AxisOpts(namexaxis_name, axislabel_optsopts.LabelOpts(rotate-30)), yaxis_optsopts.AxisOpts(nameyaxis_name), tooltip_optsopts.TooltipOpts(trigger“axis“, axis_pointer_type“shadow“), ) ) # 3. 绘制折线图 line ( Line() .add_xaxis(df_sorted[‘category‘].tolist()) .add_yaxis( “累积百分比“, df_sorted[‘cum_pct‘].tolist(), yaxis_index1, color“#d14a61“, label_optsopts.LabelOpts(is_showTrue, formatterJsCode(“function(p){return p.value‘%‘;}“)), markline_optsopts.MarkLineOpts( data[opts.MarkLineItem(y80, name“80%线“)], linestyle_optsopts.LineStyleOpts(type_“dashed“, color“#999“) ) ) ) # 4. 组合与最终配置 chart bar.overlap(line) chart.set_global_opts( yaxis_opts[ opts.AxisOpts(nameyaxis_name), opts.AxisOpts( name“累积百分比“, position“right“, max_100, interval20, axislabel_optsopts.LabelOpts(formatter“{value}%“), ) ], legend_optsopts.LegendOpts(pos_top“10%“), toolbox_optsopts.ToolboxOpts(is_showTrue), ) return chart # 使用函数 categories df[‘缺陷类型‘].tolist() values df[‘发生次数‘].tolist() chart create_pareto_chart(categories, values, “产品缺陷帕累托分析“, “缺陷类型“, “发生次数“) chart.render(“pareto_by_function.html“)通过这样的封装你可以轻松地将帕累托分析应用到销售数据客户贡献分析、库存数据SKU价值分析、客服数据问题分类分析等任何符合“二八分布”的场景中。图表不仅是一种展示工具更是驱动决策的视觉语言。掌握用代码灵活生成它的能力能让你的数据分析报告更具说服力和专业性。
返回列表