尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python Pyecharts绘制帕累托图:电商数据分析与二八法则可视化实战

Python Pyecharts绘制帕累托图:电商数据分析与二八法则可视化实战 1. 项目概述从数据到洞察帕累托图的商业价值最近在整理一个电商运营的数据复盘项目运营同学丢过来一堆商品销售数据想让我帮忙分析一下哪些是“核心贡献者”。面对几十个SKU的销售额和利润数据如果只是简单地按大小排序做个柱状图总觉得差点意思不够直观也缺乏一个强有力的分析结论来支撑后续的备货和营销策略。这时候我脑子里立刻蹦出来的工具就是帕累托图。这可不是什么新鲜玩意儿它在质量管理、库存控制、客户分析等领域早就被用烂了但正因为经典才说明其价值经久不衰。简单来说帕累托图就是那个著名的“二八法则”的可视化体现80%的结果往往来自于20%的原因。在数据分析里我们用它来快速识别出哪些少数项目比如产品、客户、缺陷类型贡献了大部分比如80%的效益或问题。对于运营同学的问题用帕累托图就能一目了然地看出是不是少数几个爆款商品贡献了绝大部分的销售额从而把资源精准地倾斜到这些“关键少数”上。这次我决定用Python来实现具体来说是pyecharts这个库。为什么是它首先ECharts的交互性和美观度在业界有口皆碑生成的图表可以直接嵌入网页或保存为高清图片汇报时逼格满满。其次pyecharts作为其Python接口封装得比较友好代码写起来相对直观。虽然像matplotlib这样的老牌库也能画但要想做出带累积百分比折线、双Y轴、并且交互流畅的帕累托图pyecharts在效率和效果上优势明显。这个笔记就是记录我如何从一堆原始数据开始一步步用pyecharts“雕刻”出一幅专业级帕累托图的全过程里面会包含数据处理的关键步骤、pyecharts配置的详细技巧以及我踩过的几个坑和对应的解决方案。2. 核心思路与数据处理为绘图准备好“食材”画图之前数据必须处理成图表库能直接“消化”的格式。对于帕累托图核心是两列数据项目名称或类别和对应的数值如销售额、故障次数。我们的目标是将这些数值从大到小排序并计算出累积百分比。2.1 数据准备与清洗假设我们手头有一份DataFrame名为df_sales包含product_name商品名和revenue销售额两列。第一步永远是查看和清洗。import pandas as pd # 假设原始数据 data { product_name: [商品A, 商品B, 商品C, 商品D, 商品E, 商品F, 商品G], revenue: [15000, 8000, 4500, 12000, 3000, 6000, 2000] } df_sales pd.DataFrame(data) print(原始数据) print(df_sales)注意实际数据可能来自CSV或数据库这里用字典模拟。务必检查缺失值df_sales.isnull().sum()和异常值比如负的销售额这些都需要在排序前处理掉。2.2 排序与累积百分比计算这是构建帕累托图的核心计算步骤。我们必须按照数值降序排列然后计算累积和以及累积百分比。# 1. 按销售额降序排序 df_sorted df_sales.sort_values(byrevenue, ascendingFalse).reset_index(dropTrue) # 2. 计算累积销售额 df_sorted[cumulative_revenue] df_sorted[revenue].cumsum() # 3. 计算累积百分比 total_revenue df_sorted[revenue].sum() df_sorted[cumulative_percentage] df_sorted[cumulative_revenue] / total_revenue * 100 print(\n排序并计算累积值后的数据) print(df_sorted)运行后你会得到一个新的DataFrame其中商品已经按销售额从高到低排列并且有了累积销售额和累积百分比两列。这里有个关键点累积百分比的计算基础是排序后的序列这样才能形成那条经典的增长曲线。2.3 格式整理与提取为了传入pyecharts绘图我们需要将处理好的数据提取成列表。通常我们需要三个列表商品名已排序、销售额已排序、累积百分比。# 提取绘图所需的数据序列 categories df_sorted[product_name].tolist() # X轴类别 values df_sorted[revenue].tolist() # 柱状图数据 cumulative_percent df_sorted[cumulative_percentage].tolist() # 折线图数据 print(f商品列表{categories}) print(f销售额列表{values}) print(f累积百分比列表{cumulative_percent})至此数据的“食材”已经备好并且按照帕累托分析的要求进行了精细加工。接下来就是进入pyecharts的厨房开始烹饪可视化大餐。3. 使用Pyecharts绘制基础帕累托图有了规整的数据绘图本身反而变得直观。pyecharts的思路是组合图表一个柱状图Bar用于显示每个项目的实际值一个折线图Line用于显示累积百分比曲线并且它们共享同一个X轴。3.1 构建双Y轴坐标系帕累托图需要两个Y轴左侧是实际数值如销售额右侧是百分比0%-100%。在pyecharts中我们通过opts.InitOpts初始化一个图表然后分别添加两个Y轴。from pyecharts import options as opts from pyecharts.charts import Bar, Line from pyecharts.commons.utils import JsCode # 初始化图表设置宽度和高度 pareto ( Bar(init_optsopts.InitOpts(width1000px, height600px)) .add_xaxis(categories) .add_yaxis( series_name销售额, y_axisvalues, yaxis_index0, # 指定使用第一个Y轴左侧 color#5793f3, # 自定义柱状图颜色 label_optsopts.LabelOpts(is_showFalse), # 默认不显示柱子上标签避免拥挤 ) .extend_axis( # 扩展出第二个Y轴右侧百分比轴 yaxisopts.AxisOpts( name累积百分比, type_value, min_0, max_100, positionright, axisline_optsopts.AxisLineOpts(linestyle_optsopts.LineStyleOpts(color#d14a61)), axislabel_optsopts.LabelOpts(formatter{value}%), # 标签显示为百分比 ) ) .set_global_opts( title_optsopts.TitleOpts(title商品销售额帕累托分析图), tooltip_optsopts.TooltipOpts(triggeraxis, axis_pointer_typecross), xaxis_optsopts.AxisOpts( name商品名称, axislabel_optsopts.LabelOpts(rotate-15) # X轴标签旋转防止重叠 ), yaxis_optsopts.AxisOpts( name销售额元, positionleft, axisline_optsopts.AxisLineOpts(linestyle_optsopts.LineStyleOpts(color#5793f3)), ), ) )这段代码做了几件关键事创建了一个Bar柱状图实例并传入了X轴数据商品名。添加了第一个Y轴数据序列“销售额”并指定其关联yaxis_index0左侧主Y轴。使用.extend_axis()方法创建了第二个Y轴用于显示百分比。我们设置了其位置在右侧(positionright)范围0-100并将标签格式化为百分比。在set_global_opts中设置了标题、提示框tooltip以及两个Y轴的基本样式。axis_pointer_typecross能让提示框同时显示柱子和折线的信息。3.2 添加累积百分比折线现在将折线图叠加到已有的柱状图坐标系上。关键是要指定折线图使用第二个Y轴yaxis_index1。# 创建折线图叠加到之前的pareto本质上是Bar实例上 line ( Line() .add_xaxis(categories) .add_yaxis( series_name累积百分比, y_axiscumulative_percent, yaxis_index1, # 指定使用第二个Y轴右侧 color#d14a61, label_optsopts.LabelOpts(formatterJsCode(function (params) {return params.value.toFixed(1) %;})), # 使用JsCode格式化标签保留一位小数 is_smoothTrue, # 让折线平滑 z_level1 # 设置折线图层级在柱状图之上确保不被遮挡 ) ) # 将折线图与柱状图合并 pareto.overlap(line)这里有几个实用技巧label_opts: 我们通过JsCode自定义了标签的显示格式将其显示为保留一位小数的百分比这使得图表上的数据点更易读。is_smoothTrue: 让累积百分比曲线变得平滑视觉上更美观也符合其连续变化的特性。z_level1: 确保折线图绘制在柱状图的上层避免被柱子遮挡。3.3 渲染与保存图表最后一步将图表渲染出来可以生成一个独立的HTML文件方便交互查看也可以保存为静态图片用于插入报告。# 渲染为HTML文件可在浏览器中打开交互 pareto.render(pareto_analysis.html) # 如果需要保存为图片如PNG可以使用snapshot-selenium或snapshot-phantomjs # 这里以render直接生成html为主更通用简便。 print(帕累托图已生成请打开当前目录下的 pareto_analysis.html 文件查看。)打开生成的HTML文件你将看到一个具备完整交互功能的帕累托图鼠标悬停在任意柱子上会显示该商品的销售额和累积百分比可以点击图例隐藏/显示柱子或折线图表也支持缩放。至此一个标准的、功能完整的帕累托图就绘制完成了。但要让图表真正服务于深度分析我们还需要给它添加一些“点睛之笔”。4. 高级定制与业务洞察增强基础图表呈现了事实而定制化图表则能强调观点引导观众发现洞察。下面介绍几个提升图表分析能力的定制技巧。4.1 突出“二八”关键分界线帕累托分析的核心是找到那个“关键少数”的临界点。我们可以在80%的累积百分比处添加一条醒目的参考线并高亮显示达到此线前的商品。# ... 在创建line图之后overlap之前 ... from pyecharts.charts import Line # 1. 计算80%线对应的数据点近似 # 找到第一个累积百分比超过80%的索引 try: idx_80 next(i for i, pct in enumerate(cumulative_percent) if pct 80) # 生成一条横跨整个X轴的80%水平线数据 line_80_data [80] * len(categories) except StopIteration: # 如果所有数据累积和都不到80%则用最后一个值 idx_80 len(categories) - 1 line_80_data [cumulative_percent[-1]] * len(categories) # 2. 创建80%参考线 line_80 ( Line() .add_xaxis(categories) .add_yaxis( series_name80% 分界线, y_axisline_80_data, yaxis_index1, linestyle_optsopts.LineStyleOpts(color#ff9900, width2, type_dashed), # 橙色虚线 label_optsopts.LabelOpts(is_showFalse), is_smoothFalse, is_symbol_showFalse, # 不显示数据点符号 ) ) # 3. 高亮显示关键商品80%线之前的柱子 # 思路重新添加一个只包含关键商品的柱状图系列用不同颜色 key_categories categories[:idx_801] key_values values[:idx_801] bar_key ( Bar() .add_xaxis(key_categories) .add_yaxis( series_name关键商品前80%, y_axiskey_values, yaxis_index0, color#f9713c, # 使用更醒目的颜色如橙色 label_optsopts.LabelOpts(is_showFalse), ) ) # 4. 按顺序叠加图表先基础柱状图再高亮柱状图再折线最后参考线 # 注意后添加的图层会覆盖在先添加的之上。高亮柱子后添加会覆盖基础柱子的颜色。 pareto.overlap(bar_key).overlap(line).overlap(line_80)这个操作极大地增强了图表的分析指导性。观众一眼就能看出哪些商品是贡献80%销售额的核心并且有一条明确的虚线作为判断基准。4.2 优化标签与提示信息默认的提示信息可能不够清晰。我们可以通过set_series_opts和set_global_opts中的tooltip和label配置进行深度定制。# 在pareto.set_global_opts中强化tooltip配置 pareto.set_global_opts( # ... 其他配置保持不变 ... tooltip_optsopts.TooltipOpts( triggeraxis, axis_pointer_typecross, formatterJsCode( function (params) { // params是一个数组包含同一X索引下所有系列的数据点 let barValue params[0].value; let lineValue params[1] ? params[1].value.toFixed(1) % : N/A; return params[0].name br/ params[0].seriesName : barValue br/ 累积百分比: lineValue; } ) // 自定义提示框内容更简洁清晰 ), ) # 为柱状图添加数据标签显示在柱子内部顶端 pareto.set_series_opts( label_optsopts.LabelOpts( is_showTrue, positioninsideTop, # 标签位置在柱子内部顶端 formatter{c}, # 显示数值 color#fff, # 白色字体在深色柱子上更清晰 font_size10 ) )自定义的tooltip格式将商品名、销售额和累积百分比在一行内清晰展示避免了默认多行显示的冗长。在柱子内部顶端显示具体数值方便快速读取又不影响整体美观。4.3 添加数据表格与动态排序对于需要深度查阅数据的场景将数据表格与图表联动是极佳的选择。pyecharts的Table组件可以做到这一点。from pyecharts.charts import Page, Table # 1. 准备表格数据 # 将DataFrame转换为表格需要的行数据 table_data [[排名, 商品名称, 销售额, 累积百分比]] # 表头 for i, row in df_sorted.iterrows(): table_data.append([ i1, row[product_name], f{row[revenue]:,.0f}, # 千位分隔符格式化 f{row[cumulative_percentage]:.1f}% ]) # 2. 创建表格 table ( Table() .add(headerstable_data[0], rowstable_data[1:]) .set_global_opts(title_optsopts.TitleOpts(title商品销售数据明细表)) ) # 3. 使用Page组件将图表和表格组合在一个HTML页面中 page Page(layoutPage.SimplePageLayout) # 简单上下布局 page.add(pareto, table) page.render(pareto_analysis_with_table.html)这样一个HTML页面里既有直观的帕累托图又有精确的数据表格分析报告的专业度和完整性瞬间提升。读者可以交互式地查看图表也可以从表格中获取精确数值进行记录或进一步计算。5. 常见问题排查与实战心得在实际操作中你可能会遇到一些意料之外的情况。这里记录了几个典型问题和我找到的解决方案。5.1 图表显示异常或空白问题描述运行代码后生成了HTML文件但打开后图表区域空白或显示异常。排查步骤检查数据首先确认categories,values,cumulative_percent这三个列表长度一致且不含NaN或None值。pyecharts对空值很敏感。检查浏览器控制台在浏览器中打开HTML文件按F12打开开发者工具查看“Console”选项卡是否有JavaScript报错。常见错误是echarts未正确加载可能是因为网络问题或本地离线环境未配置assets。使用本地资源如果处于离线环境可以在初始化图表时指定本地echarts库路径。pareto Bar(init_optsopts.InitOpts( width1000px, height600px, assets_host./assets/, # 指向本地assets目录 js_host./ ))并确保将pyecharts的静态资源文件通常通过pyecharts.render.install_js命令生成拷贝到项目目录下的assets文件夹中。简化测试尝试用最简单的数据如两个点绘制一个基础柱状图排除复杂配置导致的问题。5.2 累积百分比折线位置不正确问题描述折线图的起点不是第一个柱子的顶端或者走势很奇怪。根本原因数据未正确排序。这是最容易犯的错误。帕累托图要求原始数据必须按照分析数值从大到小排序后再计算累积百分比。如果排序步骤被遗漏或排序顺序错了比如用了升序累积百分比曲线就会完全失真。解决方案反复检查数据处理部分的代码。确保在执行df_sales.sort_values(byrevenue, ascendingFalse)时ascendingFalse参数降序设置正确。打印出df_sorted的前几行肉眼确认顺序是否正确。5.3 柱状图与折线图刻度不匹配问题描述柱子的高度和折线点的位置看起来不在同一个数量级上折线可能紧贴顶部或底部。原因分析这是因为左右两个Y轴的刻度范围没有协调好。左侧数值轴销售额的范围是数据的最小值到最大值而右侧百分比轴固定为0-100。如果销售额数值非常大比如几百万而百分比最大只有100在视觉上折线就会被压缩成接近底部的一条直线。解决方案通常不需要调整百分比轴0-100是标准。需要优化的是左侧数值轴的视觉比例。可以在set_global_opts的yaxis_opts中设置一个合理的最大值或者使用splitline分割线来增强网格参考。yaxis_optsopts.AxisOpts( name销售额元, positionleft, # 手动设置最大值使其约为数据最大值的1.2倍让顶部留白 max_int(max(values) * 1.2), axisline_optsopts.AxisLineOpts(linestyle_optsopts.LineStyleOpts(color#5793f3)), splitline_optsopts.SplitLineOpts(is_showTrue), # 显示网格线方便对比 ),5.4 关于性能与大数据量的处理场景当需要分析的商品类别非常多比如超过50个时生成的柱状图会非常拥挤X轴标签重叠交互卡顿。实战心得数据聚合在绘图前考虑将尾部贡献极小的项目合并为一个“其他”类别。这样可以大幅减少柱子数量使图表聚焦在主要项目上。# 示例将累积百分比超过95%后的商品归为“其他” threshold_idx next(i for i, pct in enumerate(cumulative_percent) if pct 95) main_categories categories[:threshold_idx1] main_values values[:threshold_idx1] main_percent cumulative_percent[:threshold_idx1] other_revenue sum(values[threshold_idx1:]) if other_revenue 0: main_categories.append(其他) main_values.append(other_revenue) # “其他”的累积百分比就是100% main_percent.append(100.0) # 然后用 main_categories, main_values, main_percent 去绘图交互优化对于类别多的场景务必启用datazoom数据区域缩放组件让用户可以自由聚焦查看特定区间。pareto.set_global_opts( # ... 其他配置 ... datazoom_opts[ opts.DataZoomOpts(type_inside), # 内置型鼠标滚轮缩放 opts.DataZoomOpts(type_slider, xaxis_index0) # 滑动条型 ], )静态导出如果交互性不是必须的且数据量极大导致HTML文件加载慢可以考虑使用snapshot-selenium等工具直接将图表渲染为静态PNG图片牺牲交互性换取性能。绘制帕累托图本身不复杂但将其融入实际的数据分析工作流并针对具体业务场景进行恰到好处的定制才是真正体现数据可视化价值的地方。从排序计算到pyecharts的图层叠加从添加参考线到组合数据表格每一步都围绕着如何更清晰、更有说服力地讲述“二八法则”这个故事。下次当你面对一堆需要区分主次的数据时不妨试试用这套方法亲手打造一个专属的帕累托分析仪表盘。
返回列表