查看全课大纲(第 29 / 45 节)

箱型图与直方图

小象实战讲义 · ECharts 数据可视化

在数据分析中,我们常常需要快速了解一组数据的整体分布特征,例如数据的集中趋势、离散程度以及是否存在异常值。本节将介绍两种在统计学和数据可视化中极为重要的图表:箱型图和直方图。通过学习,你将掌握如何使用 pyecharts 绘制这两种图表,并能够从图表中解读数据的分布信息,为后续的数据探索和报告制作打下基础。

💡 核心导读

  • 箱型图:通过最小值、下四分位数、中位数、上四分位数和最大值五个关键统计量,直观展示数据的分布范围、集中趋势和异常值。
  • 直方图:将连续数据划分为若干区间(组),用柱子的高度表示每个区间内数据的频数,用于观察数据的分布形态。
  • 关键计算:箱型图的五个关键值可以通过 pyecharts.charts.Boxplot.prepare_data() 便捷计算;直方图的频数分布则需借助 numpy.histogram 函数。
  • 图表选择:箱型图适合比较多组数据的分布差异,节省空间;直方图则能更细致地展示单一变量的数据分布密度。

一、箱型图:数据的五数概括法

箱型图,也称为盒须图或盒子图,是一种用于显示一组数据分布情况的统计图。它用一个“盒子”和两根“须”来概括数据,其核心在于五个关键数值:最小值、下四分位数(Q1)、中位数、上四分位数(Q3)和最大值。

这五个数值将数据分为四个区间,每个区间包含约25%的数据。通过箱型图,我们可以快速判断:

  • 数据范围:最大值与最小值之间的跨度。
  • 集中趋势:中位数所在位置,代表数据的中心。
  • 离散程度:盒子(IQR,即 Q3-Q1)的长度,盒子越短,数据越集中。
  • 偏态与异常值:观察中位数在盒子中的位置,以及须线外的离散点。

1.1 理解箱型图的构成

让我们通过一个简单的例子来理解这五个数值。假设我们有一组数据:[850, 740, 900, 1070, 930, 860, 950, 980, 990, 880]。

  1. 排序:首先将数据从小到大排序:[740, 850, 860, 880, 900, 930, 950, 980, 990, 1070]。
  2. 计算关键值:
    • 最小值:740
    • 下四分位数 (Q1):处于25%位置的值。对于10个数据,位置是2.5,通过插值法计算得到。
    • 中位数:处于50%位置的值。对于偶数个数据,是中间两个数的平均值:(900+930)/2 = 915。
    • 上四分位数 (Q3):处于75%位置的值。
    • 最大值:1070

在箱型图中,盒子的下边界是Q1,上边界是Q3,盒子中间的线是中位数。从盒子两端延伸出去的“须”通常延伸到最小值和最大值,但有时也会根据异常值的判断规则进行截断。

1.2 使用 pyecharts 绘制箱型图

在 pyecharts 中,绘制箱型图非常方便,因为它内置了计算五个关键值的方法 prepare_data()。

from pyecharts import options as opts
from pyecharts.charts import Boxplot

# Boxplot 期望的数据格式是列表的列表;这里只有一个系列。
v = [[850, 740, 900, 1070, 930, 860, 950, 980, 990, 880]]
boxplot = Boxplot()
boxplot_data = boxplot.prepare_data(v)
print("计算得到的关键值列表:", boxplot_data)

chart = (
    Boxplot()
    .add_xaxis(["示例数据"])
    .add_yaxis("", boxplot_data)
    .set_global_opts(title_opts=opts.TitleOpts(title="单组数据箱型图示例"))
)
chart.render_embed()
print("图表关键配置:X轴-'示例数据',Y轴-1个箱型图系列。")
单组数据的箱型图,显示四分位箱体与中位数线
图:单组数据箱型图:箱体表示四分位区间,中线为中位数,上下须线延伸到最值。手机端自动使用简化视图,点击图片可看大图。

代码输出:

计算得到的关键值列表: [[740, 857.5, 915.0, 982.5, 1070]]
图表关键配置:X轴-'示例数据',Y轴-1个箱型图系列。

运行后,将生成一个交互式箱型图。将鼠标悬停在图表上,可以清晰地看到五个关键值的具体数值。这组数据的中位数是 915,最大值 1070 对应上须端点。按 1.5×IQR 规则核验:numpy 分位口径的上下围栏为 703.75~1133.75,pyecharts prepare_data() 口径为 670~1170,1070 都没有越界,因此本组数据没有离群点。两种口径的 Q1/Q3 不同,来自分位插值算法差异。

1.3 分组箱型图比较

箱型图的强大之处在于可以轻松比较多组数据的分布。我们准备上午和下午两个时间段,A、B两组的数据进行对比。

from pyecharts import options as opts
from pyecharts.charts import Boxplot

# 上午数据:先组内类别(A/B),再跨时间段
v_morning = [
    [850, 740, 900, 1070, 930, 850, 950, 980, 980, 880, 1000, 980],  # A组上午
    [960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, 790],    # B组上午
]
v_afternoon = [
    [890, 810, 810, 820, 800, 770, 760, 740, 750, 760, 910, 920],    # A组下午
    [890, 840, 780, 810, 760, 810, 790, 810, 820, 850, 870, 870],    # B组下午
]

chart_group = (
    Boxplot()
    .add_xaxis(["A组", "B组"])  # X轴是两个分组
    .add_yaxis("上午", Boxplot().prepare_data(v_morning))  # 上午数据系列
    .add_yaxis("下午", Boxplot().prepare_data(v_afternoon))  # 下午数据系列
    .set_global_opts(title_opts=opts.TitleOpts(title="A/B组上下午数据分布对比"))
)

print("分组箱型图已生成。")
print("图表包含2个X轴分类(A组,B组),2个数据系列(上午,下午)。")
分组箱型图已生成。
图表包含2个X轴分类(A组,B组),2个数据系列(上午,下午)。

通过这个分组箱型图,我们可以直观地比较:

  • A组和B组在上午和下午的表现差异。
  • 同一组内,上午和下午的数据分布变化(如中位数是否偏移,离散程度是否变化)。
  • 是否存在异常值。

二、直方图:观察数据分布密度

直方图在外观上与柱状图相似,但其内涵和用途有本质区别。柱状图用于比较不同类别的数据大小,而直方图用于展示一个连续变量在各个取值区间内的频数或频率分布。

2.1 直方图的核心:数据分组与频数统计

绘制直方图的关键步骤是数据分组(也叫分箱)。我们需要决定将数据的整个范围划分成多少个连续的区间,然后统计落入每个区间的数据个数。

例如,我们有一组年龄数据:[22, 87, 5, 43, 56, 73, 55, 54, 11, 20, 51, 5, 79, 31, 27]。我们想了解年龄的分布,可以按 [0, 20, 40, 60, 80, 100] 进行分组,这意味着我们创建了 0-20、20-40、40-60、60-80、80-100 五个年龄区间。

2.2 使用 NumPy 计算频数分布

Python 的 NumPy 库提供了高效的 histogram 函数来完成分组和计数工作。

import numpy as np
from pyecharts import options as opts
from pyecharts.charts import Bar

ages = np.array([22, 87, 5, 43, 56, 73, 55, 54, 11, 20, 51, 5, 79, 31, 27])
bins = [0, 20, 40, 60, 80, 100]
hist, bin_edges = np.histogram(ages, bins=bins)
print("分组边界:", bin_edges)
print("对应频数:", hist)
x_labels = [f"{int(bin_edges[i])}-{int(bin_edges[i+1])}" for i in range(len(bin_edges)-1)]
chart_hist = (
    Bar()
    .add_xaxis(x_labels)
    .add_yaxis("人数", hist.tolist(), category_gap=0.1)  # 转换列表并收紧柱间距
    .set_global_opts(
        title_opts=opts.TitleOpts(title="年龄分布直方图"),
        yaxis_opts=opts.AxisOpts(name="频数"),
        xaxis_opts=opts.AxisOpts(name="年龄区间"),
    )
)
chart_hist.render_embed()
print("直方图已生成。")
print(f"X轴标签:{x_labels}")
print(f"Y轴数据(频数):{hist.tolist()}")
年龄分布直方图,横轴为年龄段、纵轴为人数
图:年龄分布直方图:按年龄段分组统计人数,柱间距收紧后更像连续分布。手机端可左右滑动查看,点击图片可看全图。

代码输出:

分组边界: [  0  20  40  60  80 100]
对应频数: [3 4 5 2 1]
直方图已生成。
X轴标签:['0-20', '20-40', '40-60', '60-80', '80-100']
Y轴数据(频数):[3, 4, 5, 2, 1]

解读:

  • 边界 [0, 20, 40, 60, 80, 100] 表示区间为 [0, 20), [20, 40), [40, 60), [60, 80), [80, 100)。注意是左闭右开。
  • 频数 [3, 4, 5, 2, 1] 表示:有3个人的年龄在 [0, 20) 岁之间;有4个人在 [20, 40);有5个人在 [40, 60);有2个人在 [60, 80);有1个人在 [80, 100)。

生成的图表清晰地显示了年龄主要集中在 40-60 岁区间,80-100 岁区间人数最少。通过调整 bins 参数,你可以改变分组的精细度,从而从不同粒度观察数据分布。

📝 动手练一练

  1. 自定义数据绘制箱型图:请你创建一组包含15个数值的列表(可自行定义,例如某商品15天的销售额)。使用 pyecharts 绘制其箱型图,并观察数据的中位数、四分位距以及是否存在异常值。

  2. 探索直方图分组的影响:使用上面的年龄数据,把 bins 改为 [0, 30, 60, 90] 重新计算频数,并比较分组变粗后对分布解读的影响。

点击查看合并参考答案
import numpy as np
from pyecharts import options as opts
from pyecharts.charts import Boxplot
from pyecharts.charts import Bar

sales_data = [[12, 15, 18, 22, 19, 25, 8, 30, 28, 21, 17, 24, 26, 5, 35]]
boxplot = Boxplot()
key_values = boxplot.prepare_data(sales_data)
print("箱型图关键值:", key_values)

ages = np.array([22, 87, 5, 43, 56, 73, 55, 54, 11, 20, 51, 5, 79, 31, 27])
bins_coarse = [0, 30, 60, 90]
hist_coarse, edges_coarse = np.histogram(ages, bins=bins_coarse)
x_labels_coarse = [f"{int(edges_coarse[i])}-{int(edges_coarse[i+1])}" for i in range(len(edges_coarse)-1)]
print("粗分组边界:", edges_coarse)
print("粗分频数:", hist_coarse)
print("粗分组标签:", x_labels_coarse)
箱型图关键值: [[5, 15, 21, 26, 35]]
粗分组边界: [ 0 30 60 90]
粗分频数: [6 6 3]
粗分组标签: ['0-30', '30-60', '60-90']

本章小结

本节我们学习了两种基础但强大的统计分布图表。箱型图以其简洁的“五数概括法”,成为比较多组数据分布、检测异常值的高效工具。直方图则通过数据分组和频数统计,揭示了连续变量的密度分布形态,是探索数据底层结构的重要方法。

📋 行动清单

  • 掌握核心计算:能使用 Boxplot.prepare_data() 计算箱型图五数,能使用 np.histogram 对数据进行分组频数统计。
  • 正确选用图表:在需要比较数据分布或检测异常值时,优先考虑箱型图;在需要观察单个连续变量的分布形态时,使用直方图。
  • 实践与解读:为自己手头的数据集分别绘制箱型图和直方图,并尝试用文字描述从图表中观察到的数据分布特征。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 08_统计分布及3D可视化.ipynb · ECharts 课程配套资源
    IPYNB · 章级代码与输出
    下载