在做损益类分析时“损益同期对比”几乎是每个月、每个季度都要出现的固定需求。过去我们习惯在宽屏PPT里放一张横向柱状图再加一条折线表示同期数横轴塞满12个月领导在会议室大屏上看还行。但现在汇报场景已经明显变了手机端查看经营看板、竖屏大屏展示、甚至把分析结论制作成竖版短视频。竖屏版损益同期对比图不是简单把原图压窄而是要在“信息密度”和“阅读动线”上重新设计。这篇文章会讲清楚一套竖屏损益同期对比综合图表的完整做法指标口径怎么定、图表类型怎么选、布局怎么排以及怎么用Python、Excel、BI工具落地。如果你正在做经营分析、财务分析或数据报表这篇可以直接收藏。竖屏版的核心难点是宽度只有不到480像素而你要在这么窄的空间里放下营业收入、成本、毛利、费用、净利润、同比、环比、预算达成等多个维度。如果还是用一张图塞所有信息结果就是横轴时间点拥挤、图例看不清、数据标签重叠。所以竖屏方案的关键不是“画图”而是“分区块”。把KPI卡片、瀑布图、同比趋势图拆成上下滚动模块让读者每次只看一个信息层级这样竖屏反而比宽屏更适合做“结论引导”。下面按指标口径、图表设计、代码实现、性能验证和常见问题五个维度展开。1. 核心能力速览能力项说明分析主题损益科目同期对比覆盖收入、成本、毛利、期间费用、营业利润、净利润适用场景月度/季度经营分析、财务汇报、竖屏大屏、手机端看板、分析短视频配图核心指标本期数、同期数、同比增减额、同比增减率、预算达成率、净利率图表组合KPI卡片 损益瀑布图 营收同比柱线图 费用结构条形图竖屏适配9:16 或 3:4 画布分区块滚动阅读工具落地Pythonpandas matplotlib / plotly、Excel、FineBI/Power BI输出格式PNG图片、长图、PDF、HTML网页批量任务可通过Python一次生成多个部门、多个月份的对比图数据量级通常为月度/季度聚合数据数据量不大普通办公电脑即可主要门槛数据口径统一、图表排版细节、中文渲染与导出清晰度2. 适用场景与使用边界竖屏损益同期对比图表适合以下几类人群财务BP、经营分析师需要在周会、月会中快速给出“利润为什么变”的直观结论。数据运营、商业分析师需要把财务指标和业务指标放在同一张竖屏看板中展示。报表开发工程师需要将分析图表嵌入移动端H5页面或企业微信/钉钉工作台。内容团队需要为分析类短视频、公众号推文制作竖版数据配图。不适合的场景也要说清楚。如果分析目的非常严肃需要精确到每一笔凭证、每一个成本中心的明细数据那“综合图表”只适合做结论展示不适合做明细溯源。损益数据本身属于企业敏感经营数据在生成图表时要注意脱敏和权限控制对外发布或制作短视频内容前必须确认数据已经通过内部审核。涉及多人协同编辑时建议使用BI工具而非直接裸传Excel文件。3. 指标口径与数据准备做任何同期对比前先统一口径。损益表同期对比最忌讳的就是“本期数用单体口径、同期数用合并口径”账面看着差很多其实是统计范围变了。下面给出一套可复用的字段设计。3.1 核心字段结构建议至少包含以下字段字段名含义示例report_date报告期间2024-06-30period_type期间类型month / quarterincome营业收入83000000cost营业成本51000000sell_expense销售费用8600000admin_expense管理费用5400000rd_expense研发费用3900000finance_expense财务费用950000other_income其他损益600000这里的单位建议统一为“元”在展示层再转换为“万元”或“亿元”。不要在数据表里混用不同单位否则图表数值会对不齐。3.2 同期口径定义不同企业“同期”的定义有差异严格自然年同期2024年6月对比2023年6月。累计同期2024年1-6月对比2023年1-6月。滚动同期过去12个月对比再往前12个月。在企业经营分析中月度对比用单月同比季度重点看累计同比。竖屏图表需要明确标注口径建议在图标题或KPI卡片角标中写清楚“单月同比”或“累计同比”避免读者误解。3.3 派生指标计算原始表通常只有科目余额画图前需要先算出派生指标毛利 营业收入 - 营业成本毛利率 毛利 / 营业收入营业利润 毛利 - 销售费用 - 管理费用 - 研发费用 - 财务费用 其他损益净利润 营业利润 营业外收支同比额 本期数 - 同期数同比率 (本期数 - 同期数) / 同期数如果企业有预算数据还要加入“预算达成率 实际数 / 预算数”。这部分最好在SQL或Python中完成不要在Excel单元格里反复手动拉公式否则每次更新数据都容易出错。4. 竖屏图表的版面设计与图表选型竖屏图表不是横向图表旋转90度而是重塑信息层级。常见竖屏比例是9:16手机全屏截图和3:4平板或公众号插图。9:16画布较长适合滚动式阅读3:4比较紧凑适合一屏展示核心结论。4.1 竖屏版式结构从上到下建议按这个顺序排列顶部标题区报表名称、报告期间、数据单位。KPI卡片区营业收入、净利润、毛利率、净利率每个卡片带同比箭头。损益瀑布图从营业收入到净利润的逐项过渡一眼看出利润去哪了。营收对比柱线图本期与同期的柱状对比叠加同比率折线。费用结构条形图销售费用、管理费用、研发费用对比。底部说明区口径说明、数据来源、制表人。每个区块在竖屏中就是一屏读者滑动时不需要横向滚动。这样的设计也方便后期把截图直接拆成短视频分镜。4.2 图表选型逻辑损益同期对比常用这几类图KPI卡片适合展示关键结论数字避免所有数字堆在一张折线图里。瀑布图展示“收入-成本-费用利润”的增减传导过程是损益分析的核心图。分组柱状图适合本期与同期的直接对比。柱线组合图柱子表示金额折线表示同比率在竖屏中要控制显示的时间点数一般不超过8个。水平条形图适合费用类科目的大小排序在窄屏中比垂直柱状图更清晰。不建议在竖屏中使用饼图和环形图因为竖屏宽度有限饼图标签很容易重叠而且损益分析更强调结构变化瀑布图和条形图比饼图更直观。5. 用Python落地竖屏损益同期对比图下面用pandas和matplotlib给出一个可运行的竖屏图表代码框架。示例数据为模拟的季度数据实际使用时替换为财务系统导出的真实数据。5.1 安装依赖如果当前环境还没有相关库先安装pip install pandas matplotlib numpy openpyxl5.2 数据准备与派生指标计算import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib import font_manager # 中文字体设置Windows 常见用 SimHeimacOS 用 PingFang SC plt.rcParams[font.sans-serif] [SimHei, PingFang SC, Microsoft YaHei, sans-serif] plt.rcParams[axes.unicode_minus] False # 模拟季度损益数据 data { 期间: [2023Q1, 2023Q2, 2023Q3, 2023Q4, 2024Q1, 2024Q2, 2024Q3, 2024Q4], 营业收入: [5200, 6100, 5800, 7200, 5800, 6900, 6600, 8300], 营业成本: [3200, 3800, 3650, 4600, 3600, 4200, 4100, 5100], 销售费用: [600, 700, 680, 820, 650, 750, 720, 860], 管理费用: [400, 450, 430, 520, 420, 470, 460, 540], 研发费用: [300, 320, 310, 350, 330, 360, 350, 390], 财务费用: [80, 90, 85, 100, 75, 80, 85, 95], 其他损益: [50, 30, 60, 40, 55, 45, 70, 60], } df pd.DataFrame(data) df[毛利] df[营业收入] - df[营业成本] df[净利润] ( df[营业收入] - df[营业成本] - df[销售费用] - df[管理费用] - df[研发费用] - df[财务费用] df[其他损益] ) df[净利率] df[净利润] / df[营业收入] * 100 # 计算同比这里以季度为周期4个季度前为同期 df[营收同比] df[营业收入].pct_change(4) * 100 df[净利同比] df[净利润].pct_change(4) * 100 print(df[[期间, 营业收入, 净利润, 净利率, 营收同比]])这段代码输出一个带期间、营业收入、净利润、净利率、营收同比的DataFrame后续图表全部基于这个表绘制。5.3 绘制竖屏画布竖屏图表关键是画布尺寸。输出9:16比例时可以设置宽7、高16输出3:4比例时可以设置宽8、高11。下面以9:16为例fig plt.figure(figsize(7, 16), dpi150) gs fig.add_gridspec(5, 1, height_ratios[0.8, 1.2, 2.0, 1.8, 1.2], hspace0.4) ax1 fig.add_subplot(gs[0]) # KPI区域 ax2 fig.add_subplot(gs[1]) # 瀑布图区域 ax3 fig.add_subplot(gs[2]) # 营收对比 ax4 fig.add_subplot(gs[3]) # 费用对比 ax5 fig.add_subplot(gs[4]) # 说明区域 # 隐藏坐标轴的KPI卡片区 ax1.axis(off) ax5.axis(off)5.4 KPI卡片区顶部的KPI卡片可以用matplotlib的text和annotate实现。这里展示“营业收入、净利润、净利率、营收同比”四个核心数。curr df.iloc[-1] prev df.iloc[-5] # 当前期和同期 ax1.text(0.5, 0.9, 损益同期对比分析, hacenter, fontsize18, weightbold) ax1.text(0.5, 0.7, f报告期{curr[期间]}单季, hacenter, fontsize11, colorgray) ax1.text(0.25, 0.45, f营业收入\n{curr[营业收入]:.0f}万, hacenter, fontsize13, color#1f77b4) ax1.text(0.75, 0.45, f净利润\n{curr[净利润]:.0f}万, hacenter, fontsize13, color#2ca02c) ax1.text(0.25, 0.12, f净利率\n{curr[净利率]:.1f}%, hacenter, fontsize13, color#d62728) ax1.text(0.75, 0.12, f营收同比\n{curr[营收同比]:.1f}%, hacenter, fontsize13, color#ff7f0e)实际项目中可以再增加红绿箭头表示同比增减方向数据多时建议直接输出为HTML看板或截图组件而不是全部画在matplotlib里。5.5 损益瀑布图瀑布图在matplotlib中没有现成函数可以借助stacked bar实现。核心思路是每个柱子的底部支撑值不同显示金额为顶部差值。labels [营业收入, 营业成本, 毛利, 期间费用, 净利润] # 以最近一期为例 income curr[营业收入] cost curr[营业成本] gross curr[毛利] expense curr[销售费用] curr[管理费用] curr[研发费用] curr[财务费用] profit curr[净利润] bottoms [0, income, income, gross, 0] values [income, -cost, gross - income, -expense, profit] colors [#1f77b4, #d62728, #2ca02c, #ff7f0e, #9467bd] for i, (label, value, bottom) in enumerate(zip(labels, values, bottoms)): ax2.bar(i, abs(value), bottombottom if value 0 else bottom - abs(value), colorcolors[i], width0.55, labellabel) ax2.text(i, bottom value (abs(value) * 0.02), f{value:,.0f} if value 0 or i in [0, 2, 4] else f{value:,.0f}, hacenter, fontsize10) ax2.set_xticks(range(len(labels))) ax2.set_xticklabels(labels, fontsize11) ax2.set_title(损益结构瀑布图万元, fontsize13) ax2.yaxis.grid(True, linestyle--, alpha0.4) ax2.spines[top].set_visible(False) ax2.spines[right].set_visible(False)注意这段瀑布图的bottom计算逻辑是在中间变量上展示累计传导实际使用时要根据当前是正数还是负数调整底部支撑。真实项目中更稳妥的做法是将盈亏传导列拆分出来逐项计算底部。5.6 营收对比柱线图营业收入本期与同期对比用分组柱状图加同比折线。ax3.bar(df[期间][4:], df[营业收入][4:], width0.35, label本期营收, color#1f77b4) ax3.bar(df[期间][4:], df[营业收入][:4], width0.35, label同期营收, color#aec7e8, alpha0.8) ax3b ax3.twinx() ax3b.plot(df[期间][4:], df[营收同比][4:], color#d62728, markero, label营收同比) ax3b.axhline(0, color#d62728, linestyle--, linewidth0.8) ax3.set_ylabel(营业收入万元) ax3b.set_ylabel(同比率%) ax3.set_title(营业收入同期对比与同比率, fontsize13) ax3.legend(locupper left, fontsize9) ax3b.legend(loclower right, fontsize9) ax3.yaxis.grid(True, linestyle--, alpha0.4)这里有一个细节双轴图很容易误导读者因为左轴和右轴刻度不同。在使用时最好把柱子的金额轴和折线的百分比轴标注清晰或者在图中注明“柱体对应左轴折线对应右轴”。5.7 费用结构条形图竖屏窄画布中费用结构用水平条形图更直观。expense_labels [销售费用, 管理费用, 研发费用, 财务费用] expense_values [curr[销售费用], curr[管理费用], curr[研发费用], curr[财务费用]] expense_prev [prev[销售费用], prev[管理费用], prev[研发费用], prev[财务费用]] y np.arange(len(expense_labels)) ax4.barh(y 0.15, expense_values, height0.3, label本期, color#ff7f0e) ax4.barh(y - 0.15, expense_prev, height0.3, label同期, color#bcbddc) ax4.set_yticks(y) ax4.set_yticklabels(expense_labels) ax4.set_title(期间费用同期对比万元, fontsize13) ax4.legend() ax4.xaxis.grid(True, linestyle--, alpha0.4)5.8 底部说明区与导出底部说明区用来写口径和单位避免图表被转发后信息缺失。ax5.text(0.02, 0.8, 说明金额单位均为万元同比为单季口径数据来源财务系统导出。, fontsize10, vatop) ax5.text(0.02, 0.5, 制表人数据分析组 报告日期2025-01-05, fontsize10, vatop, colorgray) plt.savefig(损益同期对比_竖屏版.png, dpi200, bbox_inchestight) plt.show()导出时dpi建议设置为200以上否则在手机端放大后文字会发虚。如果要做批量任务可以把这个绘图逻辑封装成函数遍历多个部门或月份自动输出多张竖屏图。5.9 批量生成多个图表如果有多个月份或部门需要生成可以封装一个函数def generate_vertical_report(df, period_label, output_path): # 根据当前期间取数 df_curr df[df[期间] period_label] # ... 复用上面的绘图代码 ... plt.savefig(output_path, dpi200, bbox_inchestight) plt.close() # 批量生成 for p in df[期间].unique(): generate_vertical_report(df, p, freport_{p}.png)这样能减少重复操作适合固定格式的月度经营分析报告。6. 用Excel实现竖屏损益同期对比如果不想写代码Excel也能完成竖屏版本只是手工排版时间会长一些。核心思路是组合图而不是单一图表。先建Sheet1做数据底表使用数据透视表或者Power Query从财务系统取数保证原始数据与图表联动。新建Sheet2作为竖屏报表画布把列宽调窄比如A到E列各设为4左右对应手机屏幕宽度。在顶部用单元格底色和合并单元格做KPI卡片手动写入本期数和同比率。插入一张瀑布图数据源选择“营业收入、营业成本、毛利、期间费用、净利润”五行的辅助数据。Excel 2016及以上版本自带瀑布图不需要手动堆柱子。再插入一张“簇状柱形图-折线图”组合图把营业收入设为柱子营收同比设为次坐标轴折线。费用结构部分改用水平条形图图例放在右上方避免挤压绘图区。最后把图表和KPI区域对齐设置页面为自定义大小建议宽度15厘米、高度26.7厘米对应9:16比例。Excel版本适合需求简单、不频繁更新的场景。缺点是透视表刷新后图表区域容易错位需要预留足够的行高并且图表不要与数据透视表直接重叠。7. 用BI工具构建竖屏移动端看板如果数据在数据库中且需要实时更新BI工具更合适。FineBI、Power BI和Tableau都支持手机端布局。以通用的BI大屏设计思路为例在仪表板中切换到手机布局/移动端布局模式通常长宽比默认就是9:16。将指标卡组件置顶展示营业收入、净利润、净利率、营收同比每个指标卡下方挂一个迷你趋势箭头。中间放瀑布图作为损益分析核心图。BI工具一般自带KPI瀑布图或自定义图表插件。底部放同期对比柱线图。横轴时间点建议不超过6个否则竖屏下文字会重叠。在组件交互设置中开启点击联动点击营收柱状图中的某个月份下面费用条形图自动过滤到该月份。BI工具的优势是权限控制、数仓直连和移动端自适应。劣势是需要维护数据模型且部分开源BI组件在竖屏下的图例、表头样式需要写CSS调整。8. 图表效果验证与性能观察图表做完不是直接发出去先做验证。尤其是在竖屏阅读场景下以下几个检查点很重要。8.1 信息正确性验证核对最后一个数据点KPI卡片、瀑布图最终净利润、营业收入对比图中的最后一根柱子三者数字必须一致。核对同比率用计算器验证(本期-同期)/同期。核对单位图表标题写“万元”数据表中不能混入“元”的数值。核对期间标签横轴是否从旧到新排列是否出现乱序。8.2 可读性验证把导出图片放到手机上看字号是否可读是关键标题字号建议不低于16pt。轴标签不低于10pt。图例不低于9pt。数据标签不低于9pt。颜色对比度要够避免浅黄色和白色文字叠加。8.3 性能观察损益数据通常是月度或季度聚合数据量级很小普通电脑不存在性能压力。但如果数据源来自明细流水比如几十万行销售订单画图前一定要先聚合。Python中建议先用pandas groupby聚合再传给matplotlib。如果直接给matplotlib传明细数据绘图会非常慢而且图表本身也没必要展示明细。BI工具则要注意组件数量一个手机看板组件超过15个时首次加载可能超过3秒建议做数据抽取或限制默认展示期数。9. 常见问题与排查方法问题现象可能原因排查方式解决方案图表中中文显示为方块当前系统没有匹配的中文字体查看matplotlib字体列表改用系统自带SimHei或安装中文字体瀑布图的数值对不上净利润中间损益项目漏项或财务费用正负号口径错误对照利润表科目逐项核对统一“费用为正数利润为负数”的建模口径竖屏导出后文字模糊dpi过低或bbox_inches设置不当放大图片查看文字边缘导出时设置dpi200以上KPI卡片和图表数字不一致手工录入或不同口径检查KPI数字是否直接引用聚合结果不要手工输入数字使用单元格或变量引用营收柱状图柱子过多横轴时间点超过12个统计维度过细换成季度或近8期滚动展示双轴图比例误导左轴和右轴刻度不匹配对比左右轴最大值在图中标注“柱体对应左轴折线对应右轴”Excel瀑布图缺少总计没有选择汇总行检查数据源结构添加“净利润”总计行并设为汇总10. 最佳实践与使用建议做竖屏损益同期对比图表时最值得坚持的几个习惯指标口径先固化。建议写一份《损益分析指标口径说明》凡是进入图表的口径都以这份文档为准避免分析团队内部对“毛利”“净利润”的理解不一致。预留模板函数。在Python项目里封装修复好的绘图函数每个月只需要替换数据源路径和报告期间就能批量生成图片。输出要分层。对外汇报用简洁版只放KPI和瀑布图内部复盘用详细版增加费用明细和同比明细。数据脱敏和安全边界。损益表属于经营敏感数据图表文件、导出图片、H5看板都要做好权限管理分享前检查是否有部门编号、成本中心名称等脱敏信息。发布前校对。最稳妥的方式是让非分析岗位的同事先看一遍图如果TA能在30秒内说出“收入涨了但利润降了主要是费用涨了”说明这张图达到了沟通效果。11. 总结与下一步竖屏损益同期对比综合图表的本质不是“把图旋转90度”而是把“收入、成本、毛利、费用、净利润”这条分析链条重新拆分成适合手机阅读的信息层级。KPI卡片负责给结论瀑布图负责讲清楚利润传导柱线组合图负责展示趋势费用条形图负责定位异常科目。建议第一次做的时候先只做一个案例取最近两个同期月份的数据输出一张包含KPI卡片和瀑布图的竖屏图。跑通后再增加费用对比和批量生成。最容易踩的坑有两个一个是中文渲染导致导出图片变方块需要提前检查字体另一个是瀑布图的底部支撑计算错误导致最后的净利润数字对不上。把这两个问题解决整张图就稳了。后续可以继续扩展的方向接入数据源定时刷新自动推送竖屏图表到企业微信群或钉钉群增加预算达成率模块让图表覆盖“同比”和“预算”双对比甚至在图表下方输出自动化文字结论形成“数据图表结论”一体的经营分析简报。