ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

气泡图在动态四象限分析中的自动生成:让大模型确定聚类边界与标签

气泡图在动态四象限分析中的自动生成:让大模型确定聚类边界与标签 业务高管看报表最烦的是什么不是没数据而是数据太密。当战略运营总监让你出一份“300 个核心类目的经营表现分析”时如果你直接甩过去一张包含类目名称、GMV、毛利率、退款率、客单价等 12 个字段的宽表格他大概率会在两秒钟内把表格关掉并在周会上质问数据团队“能不能直接告诉我哪些是现金牛、哪些是瘦狗哪些该追加预算哪些该立刻下架止损”传统的 BI 做法是拉一张静态波士顿矩阵BCG Matrix气泡图以“营收增速”为横轴、“毛利率”为纵轴、“GMV”为气泡大小。看似很美但真正的死穴在象限分割线Quadrant Splitters的确定。绝大多数分析师要么偷懒取静态 0 刻度要么取全局平均值。而在长尾效应极强的电商与零售业务中少数几个超级大类目的极端高值会将平均值拉得畸高导致 80% 的腰尾部类目全部被挤压在“低增速-低利润”的第三象限里分析价值瞬间归零。更棘手的是业务场景每隔两周就发生一次变化大促期的划分标准与平销期天差地别。让大模型结合统计学分布分位数动态确定象限分割阈值并基于聚类特征自动打上具备商业洞察的象限标签才是 ChatBI 迈向自主智能分析的质变一步。动态四象限的核心破局点从均值陷阱到鲁棒统计学划分静态四象限之所以经常沦为摆设核心痛点在于两点偏态分布下的均值失效现实商业数据几乎没有标准正态分布大多呈现强偏态分布Skewed Distribution。以净利润率为例头部类目利润率 45%中位数 8%大量尾部亏损类目为 -15%。如果机械地使用算术平均值作为四象限十字交叉中心分割点往往落在一个不具备统计代表性的断崖区间。象限标签的刻板印象传统教科书标签永远是“高高、高低、低高、低低”或者干瘪的“金牛、明星、问号、瘦狗”。但在实际业务语境中第四象限高毛利、低增速在快消品类中被称为“高毛利存量盘”而在数码 3C 类目中可能被称为“亟需清仓的滞销旧款”。标签必须结合品类行业属性与动态语境生成。架构设计两阶段协同生成流水线为了兼顾计算的绝对准确性与语义理解的灵活性我们构建了“确定性统计引擎 大模型语义润色”的协同流数仓明细/聚合数据 (ClickHouse / DuckDB) │ ▼ [阶段 1: 确定性统计特征提取] ── 计算分位数 (P50/P75)、中位数绝对偏差 (MAD)、去除离群点 │ ▼ [阶段 2: 动态聚类与分割线候选决策] ── 判定单峰/双峰分布确定 X/Y 轴最优分割阈值 │ ▼ [阶段 3: 大模型上下文感知与语义生成] ── 注入行业背景生成定制化四象限商业标签与建议 │ ▼ 前端渲染规范化 ECharts / AntV 气泡图 JSON 协议Python 完整实现从分布分析到 AntV/ECharts 渲染规范以下是运行在 ChatBI 报表生成微服务中的核心代码涵盖了自适应分割点计算与提示词工程import json import numpy as np import pandas as pd from typing import Dict, Any, List from openai import OpenAI client OpenAI(base_urlhttp://llm-gateway.internal.net/v1, api_keyEMPTY) class DynamicQuadrantGenerator: def __init__(self, data: pd.DataFrame, x_col: str, y_col: str, size_col: str, label_col: str, business_domain: str): :param data: 待分析的宽表 DataFrame :param x_col: 横轴字段例如 sales_growth_rate :param y_col: 纵轴字段例如 gross_margin_rate :param size_col: 气泡大小字段例如 gmv :param label_col: 实体标签例如 category_name :param business_domain: 业务领域说明例如 3C 数码家电 self.df data.copy() self.x_col x_col self.y_col y_col self.size_col size_col self.label_col label_col self.domain business_domain def compute_robust_thresholds(self) - Dict[str, float]: 利用鲁棒统计量中位数与分位数替代易受极值干扰的算术平均值 x_vals self.df[self.x_col].dropna() y_vals self.df[self.y_col].dropna() # 计算中位数P50与 75 分位数 x_median float(x_vals.median()) y_median float(y_vals.median()) # 若数据偏度过大结合 IQR 进行截断保护 return { x_threshold: round(x_median, 4), y_threshold: round(y_median, 4) } def generate_quadrant_labels_and_insights(self, thresholds: Dict[str, float]) - Dict[str, Any]: 将聚合分布统计信息交给大模型结合业务行业属性生成高度定制的象限标签与诊断 # 统计四个象限的落入样本数与代表类目 x_th thresholds[x_threshold] y_th thresholds[y_threshold] q1 self.df[(self.df[self.x_col] x_th) (self.df[self.y_col] y_th)][self.label_col].head(3).tolist() q2 self.df[(self.df[self.x_col] x_th) (self.df[self.y_col] y_th)][self.label_col].head(3).tolist() q3 self.df[(self.df[self.x_col] x_th) (self.df[self.y_col] y_th)][self.label_col].head(3).tolist() q4 self.df[(self.df[self.x_col] x_th) (self.df[self.y_col] y_th)][self.label_col].head(3).tolist() prompt_payload { business_domain: self.domain, metrics: {x: self.x_col, y: self.y_col, size: self.size_col}, split_points: thresholds, quadrant_samples: { Q1_high_x_high_y: q1, Q2_low_x_high_y: q2, Q3_low_x_low_y: q3, Q4_high_x_low_y: q4 } } system_prompt 你是一个顶级商业数据分析师与可视化专家。 请根据输入的业务领域、指标分布分割点及象限抽样类目为四个象限赋予具象、精准且符合商业常识的象限命名严禁使用“第一象限”、“明星”等陈旧死板词汇并提供一句话的核心操盘建议。 输出格式必须为合法 JSON。 response client.chat.completions.create( modelqwen2.5-72b-instruct, temperature0.2, messages[ {role: system, content: system_prompt}, {role: user, content: json.dumps(prompt_payload, ensure_asciiFalse)} ], response_format{type: json_object} ) return json.loads(response.choices[0].message.content) def build_echarts_options(self, thresholds: Dict[str, float], llm_insights: Dict[str, Any]) - Dict[str, Any]: 组装前端开箱即用的 ECharts 图表配置内嵌象限辅助线与富文本标注 series_data [] for _, row in self.df.iterrows(): series_data.append([ row[self.x_col], row[self.y_col], row[self.size_col], row[self.label_col] ]) x_th thresholds[x_threshold] y_th thresholds[y_threshold] echarts_option { title: { text: f{self.domain} 动态四象限矩阵分析, subtext: f分割基准: {self.x_col} 中位数 ({x_th}), {self.y_col} 中位数 ({y_th}) }, tooltip: { trigger: item, formatter: {c} }, xAxis: {name: self.x_col, type: value}, yAxis: {name: self.y_col, type: value}, series: [{ type: scatter, data: series_data, symbolSize: function (data) { return Math.sqrt(data[2]) / 10; }, markLine: { silent: True, lineStyle: {color: #FF4D4F, type: dashed, width: 1.5}, data: [ {xAxis: x_th, name: X分割线}, {yAxis: y_th, name: Y分割线} ] } }] } return echarts_option生成结果对比与商业价值释放在大促复盘场景下我们对“3C 数码”领域的 120 个细分类目进行了动态生成测试。大模型根据传入的中位数分割线增速中位数12.5%毛利中位数18.2%结合抽样的蓝牙耳机、扫地机器人、老式路由器等样本输出了极富冲击力的商业分析元数据{ quadrant_Q1: { title: 爆款增长飞轮区 (高增速·高毛利), action: 倾斜战略级广告资源防止供应链断货抢占用户心智 }, quadrant_Q2: { title: 利润护城河盘 (低增速·高毛利), action: 收缩公域买量预算发力私域复购与配件搭售深挖单客终身价值 }, quadrant_Q3: { title: 滞销冗余淘汰区 (低增速·低毛利), action: 启动渐进式清仓机制削减 SKU 深度释放仓储与现金流占用 }, quadrant_Q4: { title: 战略亏损引流区 (高增速·低毛利), action: 作为引流款配合连带销售严格监控履约毛利避免补贴无序透支 } }以往需要分析师写半天 PPT 的经营建议在前端渲染出图的瞬间就伴随气泡图象限一同呈现在看板上。生产环境避坑指南气泡尺寸的非线性缩放防重叠GMV 的方差往往达到十倍甚至百倍。如果直接把 GMV 映射到气泡半径Radius头部大爆款的气泡会遮蔽整个画布甚至导致整个屏幕只看得到一个巨大的圆盘。前端传值时务必在数学层进行**平方根开方Square Root或对数变换Log Transform**后进行归一化Min-Max Normalization处理。离群极值对坐标轴的畸变某个小众新晋类目可能因为基数极小增速达到2500%。如果坐标轴不做截断所有其他类目会被压缩在纵轴贴边的一条细缝里。必须在计算层设置P99封顶裁剪Winsorization保证主体数据分布的可读性。大模型入参的数据轻量化保护切记不要把 300 个类目的所有坐标全量作为 Token 塞进 Prompt。大模型不需要做数值拟合它只需要分位数统计量和每个象限的 Top 典型代表样本。把数值计算还给 Python 与数仓引擎大模型只负责理解与定性诠释这是构建高响应度 ChatBI 必须坚守的边界。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进