Matplotlib 数据可视化(饼图、散点图、箱线图、雷达图、误差棒图)
在数据分析的世界里,可视化是连接数据与洞察的桥梁。Matplotlib 作为 Python 中经典的可视化库,能将枯燥的数字转化为直观的图形,帮助我们快速发现数据规律。近期,我通过实践多种常见图形的绘制,深入学习了 Matplotlib 的使用方法,以下是我的学习总结与心得。
Matplotlib 数据可视化
在数据分析的世界里,可视化是连接数据与洞察的桥梁。Matplotlib 作为 Python 中经典的可视化库,能将枯燥的数字转化为直观的图形,帮助我们快速发现数据规律。近期,我通过实践多种常见图形的绘制,深入学习了 Matplotlib 的使用方法,以下是我的学习总结与心得。
一、图形分类与对应代码
(一)饼图:展示数据占比
饼图适用于呈现各部分数据在总体中所占的比例关系,通过扇形的大小直观反映占比差异。在绘制时,需要注意数据的百分比计算、标签设置以及图形样式的优化,比如是否突出某些扇形、是否添加阴影等。
1. 基础饼图
import numpy as np
import matplotlib.pyplot as plt
pie_data = np.array([20,50,10,15,30,55])
pie_labels = np.array(['A','B','C','D','E','F'])
total = pie_data.sum()
# 计算百分比并保留10位小数,确保所有百分比之和为100%
percentages = np.round(pie_data / total*100,10)
percentages[-1] = 100 - percentages[:-1].sum()
# 绘制基础饼图,设置半径和百分比显示格式
plt.pie(percentages,radius=1.5,labels=pie_labels,autopct='%.1f%%')
plt.show()
清晰标注了各部分(A-F)的占比,如 B 占 27.8%、F 占 30.6% 等,能快速看出 F 的占比最高,C 的占比最低(5.6%)。
2. 环形饼图
在基础饼图的基础上,通过wedgeprops={'width':0.7}参数可将饼图改为环形,使图形更具设计感,同时不影响占比信息的传递。
import numpy as np
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
pie_data = np.array([20,50,10,15,30,55])
pie_labels = np.array(['A','B','C','D','E','F'])
total = pie_data.sum()
percentages = np.round(pie_data / total*100,10)
percentages[-1] = 100 - percentages[:-1].sum()
# 绘制环形饼图,设置环的宽度和百分比文字距离圆心的距离
plt.pie(percentages,radius=1.5,labels=pie_labels,autopct='%.1f%%',wedgeprops={'width':0.7},pctdistance=0.75)
plt.show()
)与基础饼图的占比信息一致,但环形设计让图形更简洁,避免了传统饼图的视觉压迫感。
3. 带突出效果的分类饼图
当需要强调所有分类时,可使用explode参数让每个扇形都向外突出,并添加阴影增强立体感,这种方式在展示多分类消费数据等场景中尤为实用。
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
# 消费数据,包含8个分类
pie_data = np.array([2000,3000,10000,600,3000,2300,1500,300])
pie_labels = np.array(['服饰装扮','转账红包','餐饮美食','充值缴费','日用百货','交通出行','文化休闲','其他'])
total = pie_data.sum()
percentages = np.round(pie_data / total*100,10)
percentages[-1] = 100 - percentages[:-1].sum()
# 设置所有扇形都向外突出0.1个单位
explode = (0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1)
# 绘制带阴影和突出效果的饼图,设置起始角度为90度(从正上方开始)
plt.pie(percentages,shadow=True,explode=explode,radius=1.5,labels=pie_labels,autopct='%.1f%%',pctdistance=0.75,startangle=90)
plt.show()
可以看出,餐饮美食占比最高(44.1%),其他类占比最低(1.3%),突出效果让各分类的边界更清晰,视觉冲击力更强。
(二)散点图:探索变量关系
散点图主要用于展示两个变量之间的关系,通过每个数据点的位置,观察变量间是否存在线性或非线性关联,常用于数据分布规律的初步探索。
1. 随机数据散点图
当没有明确的变量关系时,可通过随机生成数据绘制散点图,了解散点图的基本绘制逻辑。
import numpy as np
import matplotlib.pyplot as plt
# 生成20个0-1之间的随机数作为x和y坐标
x = np.random.rand(20)
y = np.random.rand(20)
# 绘制散点图
plt.scatter(x,y)
plt.show()
数据点在坐标系内随机分布,无明显规律,这符合随机数据的特点,也帮助我熟悉了scatter函数的基本用法。
2. 有规律数据散点图
当数据存在明显的线性或非线性关系时,散点图能清晰呈现这种规律。如下代码中,y 随 x 的增大而呈近似二次函数增长,散点图可直观反映这一趋势。
import numpy as np
import matplotlib.pyplot as plt
# x从10到200,步长为10,共20个数据点
x = np.arange(10, 210, 10)
# y与x呈近似二次函数关系
y = [0.5, 2.0, 4.4, 7.9, 12.3, 17.7, 24.1, 31.5,
39.9, 49.2, 59.5, 70.8, 83.1, 96.4, 110.7,
126.0, 142.2, 159.4, 177.6, 196.8]
plt.scatter(x,y)
plt.show()
随着 x 的增大,y 呈现出明显的上升趋势,且上升速度逐渐加快,初步判断两者可能存在二次函数关系,为后续的数据分析提供了方向。
(三)箱线图:分析数据分布
箱线图(盒式图)能直观展示数据的分布特征,包括中位数、四分位数、最大值、最小值以及异常值,帮助我们快速了解数据的离散程度和集中趋势。
1. 单组数据箱线图
对于单组数据,箱线图可清晰呈现其分布情况,包括数据的集中位置和离散范围。
import numpy as np
import matplotlib.pyplot as plt
# 生成100个1-300之间的随机整数
data = np.random.randint(1,300,100)
# 绘制水平箱线图,设置宽度、填充颜色,并去除边框(vert=False表示水平方向)
plt.boxplot(data,widths=0.3,patch_artist=True,vert=False)
plt.show()
箱体的中间线代表中位数,箱体的上下边分别代表上四分位数和下四分位数,箱体之外的线段(须)延伸至最大值和最小值(排除异常值),通过箱体的长度可判断数据的离散程度 —— 箱体越短,数据越集中。
2. 两组数据箱线图对比
当需要对比两组数据的分布差异时,可将两组数据的箱线图绘制在同一图形中,便于直观比较中位数、离散程度等指标。
import numpy as np
import matplotlib.pyplot as plt
# 两组数据,可代表不同类别或不同时期的指标
data=np.array([6579.0, 6230.1, 6478.4, 6860.5, 7586.2,
7383.5, 6751.2, 6393.5, 6540.4, 7233.7])
data1=np.array([6701.7, 6085.7, 6410.2, 7090.3, 8059.2,
8248.0, 6830.0, 6610.0, 6666.7, 7578.5])
# 绘制两组数据的水平箱线图,便于对比
plt.boxplot([data,data1],widths=0.5,patch_artist=True,vert=False)
plt.show()
两组数据的箱线图并列展示,可直观发现第二组数据(data1)的中位数略高于第一组,且箱体长度更大,说明第二组数据的离散程度更高,数据分布更分散。
(四)雷达图:多维度数据对比
雷达图(极坐标图)适用于展示多维度数据,将每个维度的数值映射到极坐标的不同角度上,通过连接各维度的点形成多边形,直观对比多个对象在不同维度上的表现。
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置极角,从0到2π(0到360度),共5个点(包含起点和终点,确保图形闭合)
theta1 = np.array([0, np.pi/2, np.pi, 3*np.pi/2, 0])
# 各维度的数值(极径),此处所有维度数值均为6,代表某个对象在4个维度上表现均衡
r1 = np.array([6, 6, 6, 6, 6])
# 绘制雷达图,连接各维度的点
plt.polar(theta1, r1)
# 设置各极角对应的维度标签
radar_labels = np.array([None, '维度(B)', '维度(C)', '维度(D)', '维度(A)'])
# 将极角转换为角度(弧度转角度),并添加标签
plt.thetagrids(theta1 * 180/np.pi, radar_labels)
# 填充雷达图内部,设置透明度为0.3,增强视觉效果
plt.fill(theta1, r1, alpha=0.3)
plt.show()
多边形为正四边形(因各维度数值相同),清晰展示了该对象在维度 A、B、C、D 上的表现完全均衡,若有多组数据,可在同一雷达图中绘制多个多边形,直观对比不同对象的多维度差异。
(五)误差棒图:展示数据不确定性
误差棒图用于展示数据的测量误差或不确定性,在数据点的上下(或左右)添加线段(误差棒),线段长度代表误差范围,常见于实验数据或统计数据的可视化,帮助读者了解数据的可靠性。
1. 基础误差棒图
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
# x为5个类别(0-4)
x = np.arange(5)
# y为各分类的测量值
y = np.array([25,32,33,26,25])
# 各测量值对应的误差范围
y_offset = np.array([1.5,1,1.2,0.8,0.5])
# 绘制误差棒图,设置误差棒宽度、顶部和底部的横线(capsize)大小及厚度
plt.errorbar(x,y,yerr=y_offset,elinewidth=2,capsize=5,capthick=2)
plt.show()
,每个数据点上方和下方都有一条垂直的误差棒,误差棒的长度由y_offset决定,例如 x=1(第二个数据点)的误差范围为 32±1,通过误差棒的长短可判断各数据点的不确定性大小 —— 误差棒越短,数据越可靠。
2. 多组数据误差棒图对比
当需要对比多组数据的变化趋势及不确定性时,可在同一误差棒图中绘制多组数据,便于观察趋势差异和误差大小。
import numpy as np
import matplotlib.pyplot as plt
# 年份范围(2013-2022)
years = [2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022]
# 城市A各年份人口数
ny_population = np.array([8222830, 8272948, 8306696, 8345126, 8398748,
8437387, 8398748, 8390081, 8336817, 8323340])
# 城市B各年份人口数
la_population = np.array([3820876, 3851202, 3881622, 3918872, 3967006,
4009717, 4049581, 4089976, 4117550, 4142779])
# 城市A人口数的标准差(误差范围)
ny_std = np.array([150000, 120000, 140000, 110000, 130000,
90000, 100000, 80000, 120000, 90000])
# 城市B人口数的标准差(误差范围)
la_std = np.array([90000, 70000, 100000, 120000, 110000,
90000, 85000, 95000, 80000, 100000])
# 分别绘制城市A和城市B的人口变化及误差范围
plt.errorbar(years, ny_population, yerr=ny_std, capsize=3)
plt.errorbar(years, la_population, yerr=la_std, capsize=3)
# 设置y轴刻度标签为原始数字(避免科学计数法,更易读)
plt.ticklabel_format(style='plain', axis='y')
plt.show()
两条线分别代表城市 A 和城市 B 的人口变化趋势,城市 A 的人口始终高于城市 B,且城市 A 人口在 2018 年达到峰值后略有下降,城市 B 人口则呈持续缓慢上升趋势。同时,误差棒的长短反映了各年份人口统计数据的不确定性,例如城市 A 在 2013 年的误差较大(150000),2020 年的误差较小(80000),说明 2020 年的人口统计数据更可靠。
(六)数据计算与辅助分析
除了图形绘制,数据分析还需要结合数据计算,例如计算总和、平均值等,为图形解读提供数据支撑。以下代码通过计算两个城市的总人口和每年人口总和,进一步挖掘人口数据的规律。
import numpy as np
# 城市A各年份人口数
ny_population = np.array([8222830, 8272948, 8306696, 8345126, 8398748,
8437387, 8398748, 8390081, 8336817, 8323340])
# 城市B各年份人口数
la_population = np.array([3820876, 3851202, 3881622, 3918872, 3967006,
4009717, 4049581, 4089976, 4117550, 4142779])
# 计算城市A 2013-2022年的总人口(所有年份人口累加)
ny_total_population = np.sum(ny_population)
# 计算城市B 2013-2022年的总人口
la_total_population = np.sum(la_population)
# 计算每年两个城市的人口总和(逐年相加)
yearly_combined_population = ny_population + la_population
# 打印计算结果
print("城市A总人口:", ny_total_population)
print("城市B总人口:", la_total_population)
print("每年A和B的人口总和:", yearly_combined_population)
运行结果如下:
城市A总人口: 83432721
城市B总人口: 39849181
每年A和B的人口总和: [12043706 12124150 12188318 12263998 12365754 12447104 12448329 12480057 12454367 12466119]
从结果可以看出,2013-2022 年期间,城市 A 的总人口约为 8343 万,是城市 B(约 3985 万)的两倍多;每年两个城市的人口总和在 1204 万 - 1248 万之间,整体呈缓慢上升趋势,2020 年达到峰值(1248 万),这与误差棒图中观察到的人口变化趋势一致,进一步验证了图形所反映的规律。
二、心得与收获
(一)图形选择的核心原则
通过本次学习,我深刻认识到 “数据决定图形”—— 不同类型的数据需要匹配合适的图形才能最大化传递信息:
-
当需要展示 “占比” 时,优先选择饼图(如消费结构分析);
-
当需要探索 “变量关系” 时,散点图是首选(如分析身高与体重的关联);
-
当需要分析 “数据分布”(离散程度、中位数等)时,箱线图更合适(如不同班级学生成绩分布对比);
-
当需要展示 “多维度对比” 时,雷达图能直观呈现各维度差异(如不同产品在性能、价格、外观等维度的表现);
-
当数据存在 “不确定性”(如实验误差、统计偏差)时,误差棒图可清晰展示数据的可靠范围(如人口统计数据、科学实验数据)。
(二)代码编写的关键技巧
-
中文显示问题:Matplotlib 默认不支持中文,需通过
plt.rcParams['font.sans-serif'] = ['SimHei']设置中文字体,避免标签乱码; -
数据精度处理:在绘制饼图时,由于百分比计算可能存在四舍五入误差,需通过
percentages[-1] = 100 - percentages[:-1].sum()确保所有百分比之和为 100%; -
图形样式优化:合理使用
shadow(阴影)、explode(突出扇形)、alpha(透明度)等参数,可让图形更美观、信息更清晰; -
坐标轴设置:当数据数值较大时(如人口数),需通过
plt.ticklabel_format(style='plain', axis='y')取消科学计数法,让刻度标签更易读。
(三)从 “绘图” 到 “分析” 的思维转变
最初学习时,我更关注 “如何写出能运行的代码”,但随着实践深入,我逐渐意识到可视化的核心是 “通过图形传递数据洞察”。例如,在绘制城市人口误差棒图后,不仅要能看出人口变化趋势,还要结合误差棒的长短分析数据可靠性;在计算总人口后,要能关联图形趋势,验证数据规律。这种 “绘图 + 分析” 的结合,才是数据可视化的真正价值所在。
三、展望
-
进阶图形学习:目前主要掌握了基础图形,后续计划学习热力图、柱状图、折线图等更多图形的绘制,以及多图形组合(如子图)的使用,满足更复杂的数据分析需求;
-
交互性可视化:Matplotlib 绘制的是静态图形,未来可学习 Plotly 等库,实现交互式图形(如鼠标悬停显示数据详情、缩放图形等),提升可视化体验;
-
真实场景应用:结合实际数据集(如电商销售数据、环境监测数据)进行可视化实践,将所学知识应用到真实业务中,进一步提升数据分析和可视化能力。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)