尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
横向堆积柱状图实操:从数据预处理到峰值分布分析
横向堆积柱状图这东西单看名字好像就是“图表库里的一个选项”但真到了分析峰值分布、组分占比演进这类场景它往往比一堆折线图和普通柱状图都好用得多。我最近做完一个模拟项目X的日志峰值分布分析整份报告里最出彩的就是这张横向堆积图很多人在群里问是怎么画的、数据怎么预处理、怎么配色才能不辣眼睛。这里把完整思路和踩过的坑一次性说清楚。1. 为什么“peak distribution”要选横向堆积柱状图1.1 峰值分布的本质是“类别组成”的双重信息说到峰值分布最常见的就是一天24小时的访问量变化、一周内的故障发生次数、不同服务模块的耗时区间分布等。这类数据天然有两个维度第一个维度是“谁在什么时段/区间出现峰值”第二个维度是“这个峰值内部是由哪些细分类型堆积而成的”。如果只用普通柱状图只能看到总量高低用折线图能看到趋势但表达不了内部结构用竖向堆积图也不是不行但类别标签一多横向排布才能让每个类别的名称完整显示不用斜着歪着看图例。我做某个系统监控分析时要展示各小时段内不同错误码的分布情况。原始数据长这样横轴是小时段纵轴是错误码数量但总共有12个错误码分类如果竖向柱状图底部坐标轴的类别标签要塞进12个名字基本只能旋转90度非常难读。改成横向堆积柱状图后每一行是一个小时段每一条bar内部的颜色分段代表不同类型错误码的贡献鼠标悬停还能看细分值信息密度和可读性都上来了。1.2 横向排布在阅读顺序上的天然优势人类阅读习惯是左右扫视优先于上下扫视尤其当类别是时间序列或等级序列时横向排列能让“从早上8点到晚上10点”的演进顺序变成自下而上或自上而下的自然流动。比如分析一天不同时段内新用户、老用户、回访用户的访问量堆积竖向图时你视线要在底部标签和顶部图例之间来回跳横向图则可以把标签直接放到每一行bar的左侧省去了反复对照坐标轴的过程。从数据可视化的原则看横向堆积柱状图适合类别名称较长例如完整模块名、策略名、地区名。类别数量较多超过6个时横向优势明显。重点比较“每个类别的总量差异”的同时还想观察“同一类别内部构成的相对比例”。数据本身有顺序性时间、优先级、流程阶段横向排列更符合流程图的阅读逻辑。1.3 和其他图表的取舍对比我经常被问到为什么不直接用百分比堆积图百分比堆积图适合看“占比趋势”但如果不同时段总量差异巨大只看百分比会掩盖真实的流量峰值。比如凌晨2点的请求量只有300占比再奇特也不重要而晚上8点的请求量是3万哪怕某个错误码只占2%绝对值也有600可能比凌晨2点总量还高。所以我通常保留真实数量进行堆积横向长度直接反映总量颜色分段反映内部组成两者兼顾。只有在总量没有意义、纯粹看结构变化时才会选百分比堆积。2. 画之前必须先做的数据改造2.1 从宽表到长表堆积图的隐形门槛很多画图工具包括Python的matplotlib、Plotly、甚至Excel的堆积条形图对数据格式有隐性要求。它们需要的是“长格式”数据每一行代表一个样本点包含类别维度、分组维度、数值维度三列。如果你的数据是宽表比如时段错误码A错误码B错误码C8点10205必须先转换成时段错误码数量8点错误码A108点错误码B208点错误码C5这一步听起来简单但实际数据分析中有人直接用宽表去画画出来要么只有一段颜色要么报错。处理长宽转换建议用代码批量操作而不是手动改Excel行数一多手改必出问题。2.2 分组顺序和堆叠顺序的确定横向堆积柱状图里每个bar的各段颜色顺序由两个因素决定数据框中各分组出现的先后顺序以及绘图库内部的堆叠逻辑。默认情况下Python的matplotlib从下往上堆叠时第一个出现的分组会画在最底部而横向bar时如果invert_yaxis视觉上的“下”和“上”会对调容易搞混。建议在绘图前显式地把分组列转换为有序类别例如category_order [错误码A, 错误码B, 错误码C, ...] df[错误码] pd.Categorical(df[错误码], categoriescategory_order, orderedTrue)这样能保证无论数据怎么筛选堆叠顺序始终一致。否则同样的数据因为源文件行序变了画出来的图颜色顺序也会变报告前后不一致就很尴尬。2.3 缺失值、零值和负值处理堆积图对零值容忍度还行零值就是不画这一段。但负值会出现问题matplotlib里堆积柱遇到负值会向上或向下反向延伸视觉上出现“塌陷”非常难理解。如果是从监控系统导出的数据计数类指标不应该有负值一旦出现多半是数据修正、回滚产生的冲减记录需要先归零或做绝对值处理。缺失值更麻烦如果某时段没有某错误码很多工具会直接跳过该段导致后续所有组分的堆叠起点错位整个bar的长度都错。正确的做法是提前用pandas的pivot填充缺失值为0df_pivot df.pivot_table(index时段, columns错误码, values数量, fill_value0)再转回长表保证每个组合都存在数值为0也不缺行。3. 实操示例用Python画一张能直接放进报告里的横向堆积柱状图3.1 准备模拟数据这里以某模拟平台一周内各小时段服务告警的峰值分布为例。需求是展示不同告警级别严重、主要、次要、提示在各小时段的堆积数量并突出“严重告警”在哪些时段集中出现。先造一份接近真实分布的数据import pandas as pd import numpy as np np.random.seed(42) hours list(range(24)) levels [严重, 主要, 次要, 提示] data [] for hour in hours: # 模拟白天告警多、凌晨少的趋势 base 10 if 0 hour 6 else 80 if hour 12 else 120 if hour 20 else 60 for level in levels: if level 严重: num int(np.random.poisson(base * 0.05)) # 严重占比低 elif level 主要: num int(np.random.poisson(base * 0.2)) elif level 次要: num int(np.random.poisson(base * 0.3)) else: num int(np.random.poisson(base * 0.45)) data.append([hour, level, num]) df pd.DataFrame(data, columns[小时, 告警级别, 数量]) df.head()这里用泊松分布模拟是为了让数据更接近真实波动不完全均匀画出来才有“峰值”的样子。比例上提示告警最多、严重告警最少符合一般监控系统里的分布规律。3.2 分类排序让严重告警显示在最贴近图例位置为了让严重告警在图上最显眼我把它放在堆叠顺序的最底端横向条形图从左起始端或者最顶端从右端。一般阅读习惯是先看bar的长度总趋势再看从起点开始的颜色分段。我这里把严重告警放在最靠近起始端的位置也就是堆叠顺序第一位level_order [严重, 主要, 次要, 提示] df[告警级别] pd.Categorical(df[告警级别], categorieslevel_order, orderedTrue) # 转成长表前先确保没有缺失组合 df_pivot df.pivot_table(index小时, columns告警级别, values数量, fill_value0) df_long df_pivot.stack().reset_index(name数量) df_long.columns [小时, 告警级别, 数量]3.3 用matplotlib绘制横向堆积图不需要复杂工具原生matplotlib就能达到出版级效果。关键点在于每次绘制下一段时bottom参数要累加前面所有段的数值。我也是踩过几次坑才意识到不能直接丢一个二维数组给plt.barh就算完。import matplotlib.pyplot as plt import matplotlib.patches as mpatches colors {严重: #c0392b, 主要: #e67e22, 次要: #2980b9, 提示: #95a5a6} fig, ax plt.subplots(figsize(10, 8)) # 将“小时”按顺序排列 hours_sorted list(range(24)) left None for level in level_order: values df_long[df_long[告警级别] level].set_index(小时)[数量].reindex(hours_sorted).fillna(0).values if left is None: ax.barh(hours_sorted, values, colorcolors[level], labellevel, height0.6, edgecolorwhite) left values.copy() else: ax.barh(hours_sorted, values, leftleft, colorcolors[level], labellevel, height0.6, edgecolorwhite) left left values ax.invert_yaxis() ax.set_xlabel(告警数量) ax.set_ylabel(小时) ax.set_yticks(hours_sorted) ax.set_yticklabels([f{h}:00 for h in hours_sorted]) ax.set_title(各小时段告警级别堆积分布peak distribution) handles [mpatches.Patch(colorcolors[l], labell) for l in level_order] ax.legend(handleshandles, loclower right) plt.tight_layout() plt.savefig(peak_distribution_horizontal.png, dpi200) plt.show()图出来后你能明显看到白天时段堆积条特别长且最底端的红色段在上午10点和下午16点附近出现两个小高峰这就是所谓的“peak distribution”。总告警量在白天高但严重告警的峰值出现在业务高峰期这个信息在普通总量图中是看不到的。3.4 如果觉得matplotlib太笨重试试pandas内置绘图matplotlib的手动累加代码其实是底层逻辑。如果你不想写循环pandas的DataFrame直接plot(kindbarh, stackedTrue)也能出图df_pivot.plot(kindbarh, stackedTrue, figsize(10, 8), colorcolors)但是要注意这种快捷方式的堆叠顺序默认按列顺序从下到上而且图例顺序也跟列顺序对应。如果你对颜色、图例、边界要求高还是手动写matplotlib更自由。pandas内置方式适合作初步探索不适合最终报告出图。3.5 用Plotly做交互式横向堆积图的思路如果要交付给业务方或领导交互式版本更有冲击力。Plotly Express一行就能搞定import plotly.express as px fig px.bar(df_long, x数量, y小时, color告警级别, orientationh, title各小时段告警级别堆积分布, color_discrete_mapcolors, category_orders{小时: hours_sorted, 告警级别: level_order}) fig.show()注意在category_orders里定义小时顺序时如果小时是整数要转成字符串才能保证顺序。我在实际项目中就遇到整数轴自动排序导致凌晨0点跑到了图最上方非常头大。这个交互图适合放到HTML报告或网页看板鼠标悬停能看到每段的精确数值对于排查“某个时段具体哪个告警级别暴增”特别有用。4. 配色、标签、比例决定图表高级感的三个细节4.1 配色怎么选才不辣眼睛堆积图最容易踩的坑就是颜色太鲜艳红绿蓝紫塞满整张图看久了眼睛累打印出来也分不清。我的经验是同色系不同深浅优先比如同一大类下的细分用浅蓝、中蓝、深蓝表达既统一又有区分。需要突出某个关键分类时用高饱和度的强调色其余分类全部用低饱和度的中性色。避免红绿相邻在色盲人群中这两种颜色几乎无法区分。如果必须用红色和绿色中间隔一个其他颜色。颜色数量控制在5种以内。超过5种时看图的人已经很难记住图例对应关系不如拆成多张子图。上面示例中“严重”用深红色“主要”用橙色“次要”用蓝色“提示”用灰色既突出了重点又保持了整体协调。4.2 数值标签什么时候加、什么时候不加横向堆积图加数值标签要谨慎。如果堆叠段很窄数值标签挤在一起反而掩盖了信息。我的判断标准每个堆叠段占总长宽度超过8%时可以加数值标签。窄于8%的段只保留颜色和图例不必标数值细节放到表格或交互图里。总量标签放在bar的末端用深色加粗字体帮助快速比较不同行之间的总量。比如在上面的图里严重告警段很窄我不加标签否则会出现30个小数字挤在一条细缝里。但总量我可以加在每个bar右侧标注当小时总告警数。这样的图信息完整又不显得杂乱。如果要输出数值明细建议单独配一张CSV或附表而不是堆在图上。4.3 行长度的比例问题要不要从零开始堆积柱状图的bar长度必须从零开始否则会严重误导读者。有人为了突显差异把横轴起点设为500结果总量800和总量1000的bar视觉长度相同这在堆积图中是绝对不允许的。matplotlib里可以通过set_xlim(0, max_value)强制从零开始如果某个分组数量特别大导致其他组被压扁宁可砍掉极端异常值单独画子图也不要调整起点。这是我在画“某跨平台系统”的请求耗时分布时领悟到的有个时段出现了异常高峰导致其他时段全被压扁我当时把起点改到500想“看起来更清楚”结果被审稿人一眼看穿后来老老实实分开画。5. 真实场景中的三种变体玩法5.1 百分比堆积版只看结构不看总量当你想强调的是“各时段错误类型占比如何变化”而不是真实数量时把每行的数值转换成该行总和的百分比即可。实现上很简单在长表转换后按小时分组求和再相除。百分比堆积图对总量完全没概念适合用于对比不同规模系统之间的结构差异。比如A系统的告警总量是B系统的100倍直接比较数量没有意义但比较“严重告警占比是否升高”就有参考价值。5.2 分组堆积版多维度同时比较有时候需要同时比较两个场景下的堆积分布比如“优化前”和“优化后”的请求耗时区间分布。这时可以把两个系统并排画成两组横向堆积柱中间留一些间隔。matplotlib里可以通过在y轴上给每个类别分配两个位置实现比如小时8点对应位置0.8和1.29点对应1.8和2.2。这种图信息量大适合放在优化效果对比报告中一眼看出哪个时间段的性能瓶颈被消除了。5.3 双层横向堆积大分类下看小分类如果分类层次是“服务模块—错误类型”可以先用大分类画一层总体堆积图然后在大分类的某个子集旁边再画一张明细堆积图。这不算纯横向堆积图了但经常配合使用。我在做某图像处理Demo的内存分布分析时就先用横向堆积图展示应对不同图像尺寸时的内存占用组成缓存、纹理、中间缓冲再单独展开“中间缓冲”按图像算法阶段的细分堆积图这种层层下钻的方式比一张无比复杂的图好读得多。6. 常见问题与排查技巧实录6.1 bar的高度太挤或者太宽怎么办调整bar的height参数。默认高度约0.8在类别特别多比如24小时时可以调成0.6让bar之间留白更多。类别特别少时比如只有5个可以调成0.7甚至0.9减少空旷感。记住高度总和不要大于1否则bar之间会重叠。如果类目非常多超过40个横向堆积图就不再适合了建议改用热力图或普通折线堆叠图。6.2 堆叠顺序和图例顺序不一致怎么办这是最容易让人怀疑图表是不是画错的问题。默认情况下matplotlib的图例顺序跟绘制顺序一致但如果你用handles手动构造图例就容易错位。还有一种情况数据框的类别顺序与绘制的顺序不同导致图例第一个颜色对应的是“次要”而堆叠底部第一段是“严重”。解决办法就是在绘图前打印一下print(df_long[告警级别].cat.categories)确认顺序。图例顺序务必和堆叠顺序一一对应不然读者对不上号再好的图都白搭。6.3 反转轴后底部标签顺序反了用了invert_yaxis()后y轴刻度会从最大值到最小值排列这时候如果直接用原始整数画bar看起来“0点”在顶部还是底部取决于是否反转。我一般习惯小时从0开始但要展示一天从早到晚0点应该在底部所以需要invert_yaxis。如果你不反转则0点会在顶部视觉上一天从底部开始读懂没问题但不够直觉。建议根据报告语境决定顺序不要盲目反转。如果要让顺序变为“0点在最顶部”则不需要invert直接画。6.4 数据量大导致图例和标签重叠当月度数、堆积段数特别多时图例容易压住图主体。解决办法是把图例移到图外ax.legend(bbox_to_anchor(1.05, 1), locupper left)同时用plt.subplots_adjust(right0.8)腾出右侧图例空间。标签重叠则可以通过在数值边上添加白色描边来提升可读性或者干脆去掉数值标签。6.5 用Excel能不能画横向堆积柱状图可以。选中宽表数据插入“堆积条形图”即可得到横向堆积图。但Excel的默认配色和间距比较粗糙且堆叠顺序按照列顺序无法自定义特殊排序。如果你要做严肃的分析报告建议Excel只用来快速预览最终还是用Python出图。不过Excel有个优点修改数据后图自动更新特别适合给不写代码的同事临时出图。6.6 堆积图不适合哪些数据不是所有数据都适合堆积图。如果你的数据各组之间有明显的负相关或存在“此消彼长”的规律堆积图会掩盖负相关的细节。比如两个模块的负载是互补的一个上升另一个下降使用堆积图只能看到总量平稳看不出内部转移。这种情况应该用折线图或分组柱状图。此外组数超过10个的堆积图会沦为“彩虹图”读者无法从颜色中提取信息务必先降维合并次要组再画。7. 从图表到结论如何从横向堆积图里挖出“peak distribution”的含义7.1 找总峰值容易找结构化峰值难横向堆积图的总bar最长处就是总峰值时段但这只是第一步。真正的“peak distribution”分析要回答的是总峰值是由哪几个组分共同推高的是否存在某个组分单独在非总峰值时段冲到最高我上面那张示例图里总告警峰值在下午14点左右但严重告警最突出的时段却在上午10点和下午16点。这两个时段的严重告警占比远超其他时段说明系统在业务高峰初期和末期容易出现关键故障单纯看总量图根本发现不了。7.2 用堆积段宽度变化识别状态转移通过比较不同行之间同一颜色的宽度变化可以识别组分占比的变化模式。如果某个组分宽度从早到晚持续变宽到深夜变窄说明该组分和业务活跃度强相关如果某个组分宽度全天恒定可能是后台定时任务或基础监控产生跟业务流量无关。这种结构上的洞察是横向堆积图区别于普通图表的核心价值。7.3 结合表格数据做下钻验证画完图之后不能只停留在视觉判断。我通常会把峰值时段的数据单独筛选出来做排序peak_hours df_long[df_long[小时].isin([10, 14, 16])] peak_pivot peak_hours.pivot_table(index告警级别, columns小时, values数量, fill_value0) print(peak_pivot)这样可以精确看到上午10点的严重告警数量并进一步去日志里找对应的错误日志样本。图表用于发现异常区间表格用于定位精确对象两者配合才能形成完整分析链条。我见过不少人画完图直接写结论结果拿不出具体数字支撑被质疑后又重新跑数据反而耽误时间。8. 一份能直接复用的横向堆积图自查清单最后把我个人的提炼整理成清单画图前逐条过一遍基本不会翻车。数据是否为长表若为宽表先pivot后再画。是否存在缺失组合用fill_value0补全。各分组顺序是否显式定义建议用pd.Categorical固定。堆叠顺序和图例顺序是否一致打印categories核对。bar是否从零基线开始禁止调整x轴起点。颜色是否考虑色盲友好重点分类是否一眼可辨。bar高度是否适合类别数量一般0.6到0.8。类别顺序是否符合阅读逻辑需要时反转y轴。是否在峰值/重点行做了标注或说明数值标签是否会重叠窄段不标宽段可标。观察到的结构峰值是否有数据支撑准备附表备用。这张清单我用在很多次项目报告里每次都能提前拦住至少两个图表问题。有一次某组员画的图严重告警段和图例颜色对不上我让他先跑一遍清单他不信结果手动排查发现数据框排序的时候把“严重”和“次要”的顺序弄反了颜色错位让整张图的结论完全没法用。后来他把清单打印贴在工位上就再没犯过类似的错。横向堆积柱状图看似基础实则是数据分析里性价比非常高的可视化方式。从数据处理到绘制再到解读每一步都有容易忽略的细节但只要按上面这套流程走一遍图表既好看又能准确传达“到底哪里是峰值、峰值由什么贡献、分布结构如何演变”这些关键信息。希望这篇实操记录对正在做类似分析的朋友有帮助。
RELATED

相关推荐

Here Document与Expect:Shell自动化免交互原理与实战

Here Document与Expect:Shell自动化免交互原理与实战

写脚本自动化部署的时候,我最头疼的不是权限问题,不是变量嵌套,而是那一堆“交互式提问”。装软件时它问你y还是n,连服务器时它让你输密码,改配置时它要确认覆盖。新手很容易把Here Document和Expect混为一谈&#xff…

📅 2026/10/18 20:29:27
NAS上的全屋智能AI中枢:Miloco自动化部署实战

NAS上的全屋智能AI中枢:Miloco自动化部署实战

先聊个现象:很多朋友的智能家居玩了两三年,网关、音箱、传感器买了一堆,但日常体验还是“喊一句开灯、再喊一句关空调”,所谓“全屋智能”更像是一堆遥控器换了个叫法。真正的问题不是设备不够多,而是没有一个统一调度…

📅 2026/10/18 20:29:27
Unity 2D炮台追踪与子弹发射:旋转、射击与对象池优化

Unity 2D炮台追踪与子弹发射:旋转、射击与对象池优化

做2D游戏遇到“炮台追踪主角并发射子弹”这个需求,基本是塔防、射击、Boss战里绕不开的一环。很多刚接触Unity的朋友第一反应就是“让炮台look at主角就行”,结果一做就发现要么炮台转起来像抽搐,要么子弹满天乱飞,要么管子口和枪…

📅 2026/10/18 20:24:26
MORE NEWS

更多资讯

📰

Claude Desktop 配置 MCP server 连接本地 SQLite:Windows 11 网络驱动器路径踩坑与 TaoToken 通道实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Flink多并行度下Watermark不触发窗口的机制与排查

1. 从一个真实场景说起:多并行度下水位线为什么不触发窗口如果你写过 Flink 的窗口聚合,大概率遇到过这种诡异情况:单并行度跑得好好的,一调到多并行度,窗口就像被冻住了一样,死活不输出结果。日志里水位线…

📰

vLLM 推测解码实战:NLD 让大模型推理提速

大模型在线推理,部署上去以后最让人头疼的问题是什么?显存不够、吞吐上不去、首字延迟压不下来——这些我都遇到过,但最扎心的其实是 decode 阶段一个 token 一个 token 往外蹦,明明显存带宽也没用满,算力也没跑满&…

📰

注意力机制+CNN一维信号分类:MATLAB实现与避坑指南

简介:基于注意力机制的CNN数据分类Matlab实现资源,面向计算机、电子信息、数学等专业学生及需要完成课程设计、期末大作业或毕业设计的开发者。资源包含6个文件,其中主程序main.m为完整可运行的模型入口,4个png为网络结构或实验结…

📰

vLLM推测解码实操:从原理到调优,为大模型推理加速

1. 推测解码到底是什么:从“一个字一个字蹦”到“批量猜测再验证”1.1 为什么大模型推理这么慢:自回归的枷锁用过vLLM做线上推理服务的朋友应该都有体感,大模型生成token的速度,跟它“咬文嚼字”的方式是强绑定的。自回归解码的本…

📰

AI重塑编程行业:从LLM代码生成到可视化数据,附可复用代码案例与TaoToken统一API接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬