盒须图完全指南 - 箱线图统计分析
📋 概述
盒须图(Boxplot) 又称箱线图,是一种用于显示数据分布情况的统计图表。它能够展示数据的中位数、四分位数、异常值等统计信息,是数据分析和质量控制的利器。
核心价值
- 五数概括:最小值、下四分位、中位数、上四分位、最大值
- 异常检测:直观识别离群值和异常点
- 分布对比:并排对比多组数据的分布特征
- 稳健统计:不受极端值影响
🎯 核心概念
1. 盒须图结构
┌───┐
│ │ ← 上须(最大值或Q3+1.5*IQR)
┌───┼───┼───┐
│ │ │ │ ← 上四分位数Q3(75%)
│ ════ │ ← 中位数(50%)
│ │
│ ──── │ ← 下四分位数Q1(25%)
└───┼───┼───┘
│ │ ← 下须(最小值或Q1-1.5*IQR)
└───┘
○ ← 异常值(超出须范围的数据点)1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
关键指标:
- IQR(四分位距) = Q3 - Q1
- 上界 = Q3 + 1.5 × IQR
- 下界 = Q1 - 1.5 × IQR
2. 基础盒须图
javascript
option = {
series: [{
type: 'boxplot',
data: [
[85, 90, 95, 100, 105], // [min, Q1, median, Q3, max]
[80, 88, 92, 98, 110],
[75, 85, 90, 96, 108]
]
}]
};1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
🔧 详细配置项
完整盒须图配置
javascript
option = {
title: {
text: '学生成绩分布分析',
subtext: '盒须图展示各班级成绩分布',
left: 'center'
},
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow'
},
formatter: function(params) {
const data = params.data;
return `${params.name}<br/>
最大值: ${data[5]}<br/>
上四分位: ${data[4]}<br/>
中位数: ${data[3]}<br/>
下四分位: ${data[2]}<br/>
最小值: ${data[1]}`;
}
},
grid: {
left: '10%',
right: '10%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: ['一班', '二班', '三班', '四班', '五班'],
boundaryGap: true,
nameGap: 30,
splitArea: {
show: false
},
splitLine: {
show: false
}
},
yAxis: {
type: 'value',
name: '分数',
splitArea: {
show: true
}
},
series: [{
name: '成绩分布',
type: 'boxplot',
data: [
[60, 75, 82, 90, 98], // 一班
[55, 70, 78, 88, 95], // 二班
[65, 78, 85, 92, 100], // 三班
[58, 72, 80, 89, 96], // 四班
[62, 76, 83, 91, 99] // 五班
],
// 盒子样式
itemStyle: {
color: '#5470c6', // 填充色
borderColor: '#333', // 边框色
borderWidth: 1
},
// 高亮样式
emphasis: {
itemStyle: {
color: '#91cc75',
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.3)'
}
}
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
带异常值的盒须图
javascript
// ECharts会自动计算五数概括
const rawData = [
[85, 90, 92, 95, 98, 100, 102, 105, 120], // 包含异常值120
[78, 82, 85, 88, 90, 92, 95, 98],
[70, 75, 78, 80, 82, 85, 88, 90, 110] // 包含异常值110
];
option = {
series: [{
type: 'boxplot',
data: rawData,
// 自定义异常值判断
boxWidth: [7, 50], // [最小宽度, 最大宽度]
// 标记异常值
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
]
}
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
💡 实战案例
案例1:多班级成绩对比
javascript
// 原始成绩数据
const classScores = [
// 一班(30人)
[78, 82, 85, 88, 90, 92, 93, 95, 96, 98, 99, 100,
75, 80, 83, 86, 89, 91, 94, 97, 72, 77, 81, 84, 87, 76, 79, 85, 90, 95],
// 二班(30人)
[65, 70, 72, 75, 78, 80, 82, 85, 87, 88, 90, 92,
68, 73, 76, 79, 81, 84, 86, 89, 62, 67, 71, 74, 77, 75, 80, 83, 88, 91],
// 三班(30人)
[80, 82, 84, 86, 88, 90, 92, 94, 95, 96, 97, 98,
78, 81, 83, 85, 87, 89, 91, 93, 82, 85, 88, 90, 92, 86, 89, 91, 94, 96]
];
// 计算五数概括
function calculateBoxplotData(data) {
const sorted = [...data].sort((a, b) => a - b);
const min = sorted[0];
const max = sorted[sorted.length - 1];
const q1Index = Math.floor(sorted.length * 0.25);
const medianIndex = Math.floor(sorted.length * 0.5);
const q3Index = Math.floor(sorted.length * 0.75);
const q1 = sorted[q1Index];
const median = sorted[medianIndex];
const q3 = sorted[q3Index];
return [min, q1, median, q3, max];
}
option = {
title: {
text: '三个班级数学成绩对比',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: function(params) {
const [min, q1, median, q3, max] = params.data;
return `${params.name}<br/>
<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:#5470c6;"></span>
最高分: ${max}<br/>
上四分位: ${q3}<br/>
中位数: ${median}<br/>
下四分位: ${q1}<br/>
最低分: ${min}<br/>
<span style="color:#999;font-size:11px;">IQR: ${q3 - q1}</span>`;
}
},
xAxis: {
type: 'category',
data: ['一班', '二班', '三班']
},
yAxis: {
type: 'value',
name: '分数',
min: 60,
max: 100
},
series: [{
type: 'boxplot',
data: classScores.map(calculateBoxplotData),
itemStyle: {
color: '#5470c6',
borderColor: '#333'
}
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
案例2:产品质量监控
javascript
option = {
title: {
text: '产品尺寸质量监控',
subtext: '每日抽检样本分布(标准值:100mm ± 2mm)',
left: 'center'
},
tooltip: {
trigger: 'item'
},
xAxis: {
type: 'category',
data: Array.from({length: 7}, (_, i) => `第${i + 1}天`)
},
yAxis: {
type: 'value',
name: '尺寸(mm)',
min: 96,
max: 104
},
series: [{
type: 'boxplot',
data: [
[98.5, 99.2, 100.0, 100.5, 101.2],
[98.8, 99.5, 100.1, 100.6, 101.0],
[97.5, 98.8, 99.8, 100.8, 102.5], // 第三天波动大
[99.0, 99.6, 100.0, 100.4, 100.9],
[98.9, 99.4, 100.1, 100.5, 101.1],
[99.1, 99.7, 100.2, 100.6, 101.0],
[98.7, 99.3, 99.9, 100.4, 100.8]
],
itemStyle: {
color: function(params) {
// 超出标准的标红
const data = params.data;
if (data[0] < 98 || data[4] > 102) {
return '#ee6666';
}
return '#91cc75';
}
}
}],
// 添加标准线
markLine: {
data: [
{ yAxis: 100, name: '标准值' },
{ yAxis: 98, lineStyle: { color: '#ff0000', type: 'dashed' } },
{ yAxis: 102, lineStyle: { color: '#ff0000', type: 'dashed' } }
]
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
⚠️ 常见问题
问题1:数据格式错误
症状:盒须图不显示
解决:
javascript
// ❌ 错误:直接传入原始数据
series: [{
type: 'boxplot',
data: [[85, 90, 92, 95, 98]] // ECharts需要预处理
}]
// ✅ 正确:ECharts会自动计算,或使用echartsStat预处理
import { boxplotTransform } from '@visactor/vutils';
const transformed = boxplotTransform(rawData);1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
问题2:盒子太窄或太宽
解决:
javascript
series: [{
type: 'boxplot',
boxWidth: [10, 40] // [最小宽度, 最大宽度]
}]1
2
3
4
2
3
4
🎯 最佳实践
1. 数据预处理
javascript
// 使用echarts-stat库
import { boxplotTransform } from 'echarts-stat';
const rawData = [
[85, 90, 92, 95, 98, 100, 102],
[78, 82, 85, 88, 90, 92]
];
const result = boxplotTransform(rawData);
// result.boxplotData: [[min, Q1, median, Q3, max], ...]
// result.outliers: 异常值数组1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
2. 颜色语义化
javascript
itemStyle: {
color: function(params) {
const iqr = params.data[3] - params.data[1];
// IQR越大表示离散程度越高,用暖色
if (iqr > 10) return '#ee6666';
if (iqr > 5) return '#fac858';
return '#91cc75';
}
}1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
3. 结合散点图
javascript
series: [
{
type: 'boxplot',
data: boxplotData
},
{
type: 'scatter',
data: rawPoints, // 原始数据点
symbolSize: 5,
itemStyle: {
opacity: 0.5
}
}
]1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
📊 性能指标
| 数据量 | 渲染时间 | 建议 |
|---|---|---|
| <100组 | 10ms | 无限制 |
| 100-500组 | 30ms | 正常 |
| >500组 | 80ms | 考虑采样 |
🔗 相关链接
- 散点图高级.md)
- visualMap视觉映射
💎 总结
盒须图核心价值:
- ✅ 五数概括数据分布
- ✅ 快速识别异常值
- ✅ 多组数据分布对比
- ✅ 稳健的统计展示
适用场景:
- 学生成绩分析
- 产品质量监控
- 实验数据统计
- 金融风险评估
掌握盒须图,让数据分析更科学!📦
盒须图统计分析
{
"title": {
"text": "考试成绩分布",
"left": "center"
},
"tooltip": {
"trigger": "item"
},
"xAxis": {
"type": "category",
"data": [
"班级A",
"班级B",
"班级C",
"班级D"
]
},
"yAxis": {
"type": "value",
"name": "分数"
},
"series": [
{
"type": "boxplot",
"data": [
[
60,
72,
78,
85,
92,
98
],
[
55,
68,
75,
82,
90,
95
],
[
65,
75,
80,
88,
95,
100
],
[
58,
70,
76,
83,
91,
96
]
],
"itemStyle": {
"color": "#5470c6",
"borderColor": "#333"
}
}
]
}