← 返回 Skill 列表
extension
分类: 数据与分析无需 API Key

商业图表生成·12类咨询图(BCG·波特五力·瀑布·SWOT·MECE)

你给我一段业务数据,我还你一张能直接塞进汇报 PPT 的咨询级矢量图。覆盖 BCG 矩阵、波特五力、增长瀑布、SWOT、MECE 逻辑树、竞争格局象限、价值链、安索夫矩阵、龙卷风敏感性、三层增长 S 曲线、优先级矩阵、战略金字塔共 12 类——都是 Excel 和通用图表库画不了的图。输出 SVG 可直接插入 Word / PPT / 网页,在 PPT 里取消组合后还能二次改字改色。零第三方依赖,纯 Python 标准库,离线可跑;内置 12 套示例数据,一条命令预览全部效果。

person作者: user_69f3cf82hubcommunity

商业图表生成(咨询风)

〇 定位

通用图表库(smart-charts、Excel、matplotlib)会画柱状图折线图,但画不了咨询顾问天天在用的那批图——BCG 矩阵、波特五力、增长瀑布、MECE 问题树、龙卷风敏感性。这类图过去只能手工在 PPT 里拼。

本技能把 12 类咨询专用图做成可批量生成的矢量图:给一段 JSON 数据 → 出一张可直接放进汇报材料的 SVG。

  • 零依赖:只用 Python 标准库,不装任何包,离线可跑。
  • 矢量输出:SVG 可直接插入 Word / PPT / 网页,放大不失真,可在 PPT 里取消组合后二次编辑。
  • 中文友好:内置中文字体栈与 CJK 折行算法,长标签自动换行不溢出。

一 触发场景

  • 用户要做汇报材料/方案/董事会材料,需要配图。
  • 用户提到下列任一图名:BCG 矩阵、波特五力、瀑布图/桥接图、SWOT、逻辑树/问题树、价值链、安索夫矩阵、龙卷风图/敏感性分析、S 曲线/三条曲线、优先级矩阵、金字塔、象限图/竞争格局。
  • 用户说"画个图""出个图表""配张图",且语境是商业分析而非纯数据可视化。
  • 不触发:只要通用图表(柱状/折线/饼图)——那用 smart-charts 或 Excel 更合适。
  • 不触发:只要位图(PNG/JPG)且场景是公众号/微信——SVG 在部分微信场景不渲染,需先转图。

二 选图指南(最重要的一步)

先判断用户要表达什么关系,再选图。选错图比画错图更致命。

| 用户想表达 | 用这个 | type | |---|---|---| | 业务/产品组合怎么排兵布阵 | BCG 增长-份额矩阵 | bcg | | 这个行业赚不赚钱、利润被谁拿走 | 波特五力 | five_forces | | 从一个数到另一个数,中间增减怎么来的 | 增长瀑布 / 桥接图 | waterfall | | 内外部优劣势盘点 | SWOT | swot | | 一个大问题怎么拆成不重不漏的小问题 | MECE 逻辑树 | mece | | 玩家之间怎么站位(自定义两个维度) | 竞争格局象限 | quadrant | | 利润沉淀在价值链的哪个环节 | 波特价值链 | value_chain | | 增长从哪来(老产品老市场→新产品新市场) | 安索夫矩阵 | ansoff | | 哪个变量对结果影响最大 | 龙卷风敏感性 | tornado | | 新旧业务怎么接力、什么时候到顶 | 三层增长 S 曲线 | scurve | | 一堆举措先做哪个 | 优先级矩阵(影响力×可行性) | priority | | 从使命到动作的层层拆解 | 战略金字塔 | pyramid |

三 三分钟上手(渐进式)

从"看一眼效果"到"批量出图",四步递进。第一次用建议完整走一遍,之后直接跳到第 3 步。

PY="C:/Users/ghszb/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
S="C:/Users/ghszb/.workbuddy/skills/consulting-charts/scripts"

# 第 1 步:看全部图表类型(30 秒)
"$PY" "$S/make_chart.py" --list

# 第 2 步:看效果(12 套内置示例一次出齐,第一次必跑)
"$PY" "$S/make_chart.py" --demo all --out-dir ./gallery
"$PY" "$S/build_gallery.py"      # 生成 gallery.html,一屏预览 12 张

# 第 3 步:正式出图(--data 接受文件路径,也接受直接粘 JSON 字符串)
"$PY" "$S/make_chart.py" --data spec.json --out 战略组合.svg

# 第 4 步:批量出图(spec.json 写成数组即可)
"$PY" "$S/make_chart.py" --data specs.json --out-dir ./out

最小可用只需要两条命令:把示例 spec 改三个数字 → 出图。

# 第 5 步(可选):一键自检环境是否正常 —— 16 项断言,全过返回 0
"$PY" "$S/make_chart.py" --selftest

命令与参数总表

| 参数 | 作用 | 备注 | |---|---|---| | --list | 列出 12 种图表类型 | 退出码 0 | | --demo <type>\|all | 用内置示例出图 | 与 --data 互斥 | | --data <路径\|JSON串\|-> | 出图数据源 | - 表示从 stdin 读 | | --type <type> | spec 没写 type 时用它 | 与 spec 里的 type 冲突会报错 | | --out <文件> | 单图输出路径 | 批量模式禁用(用 --out-dir) | | --out-dir <目录> | 批量输出目录 | 默认 . | | --selftest | 运行 16 项内置断言 | 全过 0,有失败 3 |

四 完整实战案例(照抄即可跑)

场景:给董事会汇报"今年营收从 120 到 158 是怎么来的,明年增长从哪来"。

第一步 · 选图。营收从 A 到 B、中间增减构成 → waterfall(增长瀑布);明年增长来源 → ansoff(安索夫矩阵)。两张图够了,不要堆满。

第二步 · 写 spec.json(数字来自财务口径,不编):

{"type":"waterfall","title":"营收增量的 76% 来自量增,涨价贡献为负",
 "subtitle":"2026 财年 · 单位:百万元","start":120,"unit":"百万元",
 "steps":[{"label":"销量增长","value":41},
          {"label":"新品上市","value":16},
          {"label":"售价下滑","value":-12},
          {"label":"汇率损失","value":-7}]}

第三步 · 出图:

"$PY" "$S/make_chart.py" --data spec.json --out 营收桥接.svg

第四步 · 过质量门(见第七节):标题写的是结论不是"营收分析";4 个条目 ≤8;数字与财务口径一致;标签无溢出。

产出:营收桥接.svg,1240×780,矢量。插入 PowerPoint 后右键「转换为形状」即可改配色与文字。注意:steps 的合计(120+41+16-12-7 = 158)由脚本自动算出终值柱,不必手动传。

五 数据格式

spec.json 通用字段:type(必填)、title、subtitle、foot、w(默认 1240)、h(默认 780)。 以下为各 type 的专属字段。

bcg — BCG 矩阵

items[]:name、x 相对份额(0–1,越大越靠左)、y 市场增长率(0–1)、size 营收

{"type":"bcg","title":"业务组合诊断","items":[
  {"name":"智能传感","x":0.86,"y":0.78,"size":320},
  {"name":"代工制造","x":0.80,"y":0.16,"size":460}]}

five_forces — 波特五力

forces[]:name、score(0–5)、note;center 中心文案

{"type":"five_forces","center":"行业\n吸引力","forces":[
  {"name":"现有竞争者","score":4.5,"note":"同质化严重"},
  {"name":"替代品威胁","score":2.5,"note":"短期可控"}]}

waterfall — 增长瀑布

start 期初值;steps[]:label、value(可正可负);可选 start_label/end_label/unit。终值柱由脚本自动求和。

{"type":"waterfall","start":120,"unit":"百万元","steps":[
  {"label":"销量增长","value":28},{"label":"售价下滑","value":-19}]}

swot — SWOT

S/W/O/T 各为数组,元素可为字符串或 {text, note}

mece — MECE 逻辑树

root 根问题;branches[]:name、children[](元素为字符串或 {name, note})

quadrant — 竞争格局象限

xlabel/ylabel/quadrants(四个象限名,从左上顺时针);items[]:name、x、y、size

value_chain — 价值链

support[] 支持活动(自上而下);primary[] 主活动({name, margin});margin_label

ansoff — 安索夫矩阵

market_penetration / product_development / market_development / diversification

tornado — 龙卷风敏感性

base 基准值;factors[]:name、low(负向)、high(正向)。自动按影响幅度排序,无需手工排。

scurve — 增长 S 曲线

years 横轴年数;curves[]:name、ceiling 天花板、steepness 陡峭度、mid 拐点位置

priority — 优先级矩阵

同 quadrant,默认象限名为「立即做 / 重点规划 / 顺手做 / 暂缓」

pyramid — 战略金字塔

levels[]:name、items[](自上而下,顶层最窄)

六 输出与集成

  • 默认输出 .svg。插入 Word / PPT:直接「插入 → 图片」;PPT 中右键「转换为形状」可二次编辑配色与文字。
  • 需要位图(PNG)时,用浏览器打开 SVG 截图,或让 agent 调用图片转换工具——本技能刻意不引入 cairosvg 等依赖。
  • 画布尺寸:w/h 可调。默认 1240×780(16:10),适合单页放一张图;要做 PPT 整页配图可用 w:1600, h:900。

七 质量门(交付前自检)

  • [ ] 图型选对了吗?(对照第二节选图指南)
  • [ ] 标题写的是结论还是"XX分析"?优先用结论式标题(如"主业见顶,第二曲线尚未接棒")。
  • [ ] 数字与源文件一致,无凭空编造的数据。
  • [ ] 标签是否溢出?长文本用 note 拆成副行,或调大 w。
  • [ ] 气泡/条形数量 ≤8,超过就先归类合并——图一乱结论就没了。
  • [ ] 跑过 --demo 确认渲染正常再交稿。

八 常见错误与应对(Anti-Patterns)

| 常见错误做法 | 为什么会错 | 正确做法 | |---|---|---| | 用柱状图代替瀑布图 | 看不出"从 A 到 B 中间增减是怎么来的",这是瀑布图唯一存在的理由 | 用 waterfall,steps 传正负值 | | 标题写「营收分析」「业务组合」 | 标题是废话,读者看完不知道结论 | 写结论:"营收增量的 76% 来自量增" | | BCG 气泡一铺十几个 | 图一乱结论就没了,等于没画 | 先归类合并,压到 ≤8 个 | | BCG/象限的 x/y 填绝对值(如填营收 320) | 坐标是相对位置 0–1,填绝对值会让气泡全挤在角落 | 先归一化到 0–1;绝对值放 size | | 给 tornado 手工排序 factors | 脚本自动按影响幅度排序,手工排反而会覆盖正确顺序 | 按业务顺序填即可,排序交给脚本 | | 条目文字超过 12 字仍硬塞进 name | 会挤爆画布或互相重叠 | 主标不超过 10–12 字,补充说明拆到 note | | 直接把 SVG 塞进公众号/微信 | 部分微信与旧版浏览器不渲染 SVG | 先转 PNG 再上传 | | 用 matplotlib 硬画 BCG / 龙卷风 | 四象限底色、气泡标注、自动折行都要手写,产出还不能二次编辑 | 用本技能,输出可在 PPT 里转形状继续改 | | 一次性出十几张图塞进一份材料 | 董事会材料一页一个结论,图多说明没想清楚 | 先定每页结论,一页一图 | | 同时传 --demo bcg --data spec.json | 以为两个都生效,实际用户数据被静默丢弃 | 二选一;新版已显式报错(退出码 2),不再静默 | | 指望 --type 覆盖 spec 里的 type | 旧版 --type 是死参数,完全不生效 | 新版:spec 无 type 时生效,冲突时明确报错 | | 在 spec 的 out 里写 ../xxx.svg 想指定上级目录 | 会写穿 --out-dir,污染预期外的位置 | 新版已净化为 <out-dir>/xxx.svg;要换目录请用 --out-dir | | 批量数组里混进字符串当占位 | 旧版抛裸 AttributeError 中断整批 | 数组每项必须是对象;新版记为单张失败,其余继续 | | 用 Excel 另存的 GBK 编码 JSON 当 spec | 旧版抛裸 UnicodeDecodeError | 新版自动兜底 UTF-8/BOM/GBK/GB18030 |

九 异常与兜底

所有报错统一以 [错误] 前缀打到 stdout(不是 stderr),便于 agent 直接抓取。

| 现象 | 原因 | 处理 | |---|---|---| | [错误] 未知图表类型 '' | spec 漏了 type,或 type 拼错/大小写不对 | 在 spec 顶层加 "type":"bcg";跑 --list 复制准确名称 | | [错误] 未知图表类型 'nope'(批量里 [失败]) | 同上,发生在批量第 N 张 | 批量不会中断,其余照常出,最后看汇总行定位 | | [错误] 元素不是 JSON 对象(收到 str) | 批量数组里混进了字符串/数字/数组 | 数组每一项都必须是 {...} 对象 | | [错误] 找不到 spec 文件:xxx | 路径写错或文件不在当前目录 | 核对路径;也可直接粘 JSON 字符串,或用 --data - 从 stdin 读 | | [错误] JSON 解析失败 | 尾逗号、单引号、注释 | JSON 不支持注释与尾逗号,先用编辑器校验 | | [错误] 字段 w 必须是整数,收到 'abc' | w/h 传了非数字 | 传数字,如 "w":1600 | | [错误] --demo 与 --data 不能同时传 | 两个数据源都给了 | --demo 会覆盖你的数据,故显式拒绝;二选一 | | [错误] --type bcg 与 spec 里的 type swot 冲突 | 命令行与 spec 各写了一个 type | 只保留一个;--type 仅在 spec 没写 type 时生效 | | [错误] 批量模式请用 --out-dir | 批量出图却传了 --out | 批量用 --out-dir ./out,文件名由 spec 的 out 或 type 决定 | | [错误] 未预期的内部错误:XxxError | 兜底分支,理论上不该出现 | 带上完整命令与 spec 反馈;退出码 3 | | [依赖缺失] No module named 'svgkit' | 只复制了 make_chart.py | 本技能零第三方依赖,把整个 scripts/ 目录一起复制 | | 文字重叠/挤出画布 | 标签过长或条目过多 | 条目压到 8 个以内;长句拆 note;调大 w/h | | 中文字体显示成方框 | 目标机缺中文字体 | SVG 已内置 Microsoft YaHei/PingFang SC 字体栈,一般无需处理 | | 输出 SVG 在浏览器里空白 | 文件未写完或路径含特殊字符 | 用 XML 解析器验一次;路径避免中文以外的特殊字符 |

退出码(封闭,只有三个)

| 码 | 含义 | 典型场景 | |---|---|---| | 0 | 成功 | 单图出图成功;批量全部成功 | | 2 | 输入/使用错误 | 坏 JSON、未知 type、文件不存在、参数互斥、w 非数字;批量中任意一张失败也是 2 | | 3 | 环境或意外错误 | 依赖缺失、未预期内部异常、Ctrl+C 中断 |

退出约定:所有错误以 [错误] 前缀输出到 stdout 并退出,不产出半截 SVG;成功时逐张打印 [生成] 绝对路径。 批量模式下单张失败不中断其余,最后打印 批量完成:成功 X / 失败 Y / 共 Z 并逐条列出失败原因;只要有一张失败就返回 2。

输出路径一定是干净的

spec 里的 out 会被净化后再拼到 --out-dir 下:目录分隔符、盘符一律剥掉,只留最后一段文件名; 空名回退到 <type>.svg;缺 .svg 自动补上;Windows 非法字符 <>:"|?* 替换成 _。 所以 "out": "../../evil.svg" 只会写成 <out-dir>/evil.svg,不会写穿输出目录。

十 已验证

以下全部为 2026-09-15 在 Python 3.13.12 上实跑确认,可用 --selftest 一键复现(16 项断言)。

  • --selftest:16 项内置断言全过,退出码 0。
  • 12 种图全部通过生成测试:XML 合法、零元素越界、每张非空(实测 2026-09-03,Python 3.13.12)。
  • 12 类全部内置 --demo 示例,--demo all --out-dir 稳定产出 12 个 SVG。
  • 零第三方依赖,Python 3.9+ 可直接运行。
  • 批量模式:含 1 个未知 type 的 3 张数组 → 成功 2 / 失败 1,退出码 2,未中断。
  • 批量模式:数组混入字符串元素 → 该张记 [失败] 元素不是 JSON 对象,其余继续,不再抛 AttributeError。
  • GBK / UTF-8 / UTF-8-BOM 三种编码的 spec 文件均可正常读取(旧版 GBK 会抛裸 UnicodeDecodeError)。
  • --data 指向不存在的文件 → [错误] 找不到 spec 文件,退出码 2(旧版误报成 JSON 解析失败)。
  • --data - 从 stdin 读 spec 可用。
  • --demo 与 --data 同时传 → 显式报错退出码 2(旧版会静默丢弃 --data)。
  • --type 在 spec 无 type 时生效(实测 --type waterfall 正确渲染出瀑布图),冲突时报错。
  • out 路径注入 "../INJECTED.svg" → 收敛到 <out-dir>/INJECTED.svg,未越界。
  • w 传 "abc" → [错误] 字段 w 必须是整数,退出码 2。
  • 顶层兜底:注入 RuntimeError 后返回 [错误] 未预期的内部错误 + 退出码 3,无裸 traceback。
  • 依赖守卫:只复制 make_chart.py 而缺 svgkit 时给出 [依赖缺失] 与修复指引,退出码 3。