day-044-Matplotlib进阶-高级图表
2026/7/28 0:26:38 网站建设 项目流程

Day 44:Matplotlib 进阶——统计图表与3D绘图

柱状图、折线图、饼图已经熟练了。今天学更有"分析味"的图表:箱线图(看分布)、小提琴图(看分布形状)、六边形热力图(大数据散点)、以及 Matplotlib 的 3D 功能。


一、箱线图 boxplot()——一眼看清数据分布

箱线图是数据分析和论文中最常用的统计图之一,能同时展示中位数、四分位数、异常值。

importmatplotlib.pyplotaspltimportnumpyasnp plt.rcParams["font.sans-serif"]=["SimHei"]plt.rcParams["axes.unicode_minus"]=Falsenp.random.seed(42)# 模拟数据:四个班级的考试成绩class_A=np.random.normal(75,10,50)# 平均75,标准差10class_B=np.random.normal(80,8,50)# 平均80,标准差8class_C=np.random.normal(70,15,50)# 平均70,标准差15(离散大)class_D=np.random.normal(85,12,50)# 平均85,标准差12data=[class_A,class_B,class_C,class_D]labels=["一班","二班","三班","四班"]fig,axes=plt.subplots(1,2,figsize=(14,5))# --- 图1:基础箱线图 ---bp=axes[0].boxplot(data,labels=labels,patch_artist=True,showmeans=True)# 配色colors=["#FF6B6B","#4ECDC4","#45B7D1","#96CEB4"]forpatch,colorinzip(bp["boxes"],colors):patch.set_facecolor(color)patch.set_alpha(0.7)axes[0].set_ylabel("考试成绩",fontsize=12)axes[0].set_title("班级成绩箱线图",fontsize=14,fontweight="bold")axes[0].grid(True,alpha=0.3,axis="y")# --- 图2:横向箱线图 + 散点叠加 ---bp2=axes[1].boxplot(data,labels=labels,patch_artist=True,vert=False,showmeans=True,meanprops=dict(marker="D",markerfacecolor="red",markersize=8))forpatch,colorinzip(bp2["boxes"],colors):patch.set_facecolor(color)patch.set_alpha(0.5)# 叠加原始数据点fori,(d,color)inenumerate(zip(data,colors),1):jitter=np.random.normal(0,0.04,len(d))# 加抖动避免重叠axes[1].scatter(d,i+jitter,alpha=0.4,s=20,color=color,edgecolor="white",zorder=3)axes[1].set_xlabel("考试成绩",fontsize=12)axes[1].set_title("横向箱线图 + 原始数据点",fontsize=14,fontweight="bold")axes[1].grid(True,alpha=0.3,axis="x")plt.tight_layout()plt.show()

箱线图怎么读?

┬ ─── 最大值(上边缘) │ │ ┬ ─── 上四分位数 Q3(75%) │ │ │ ───┼─── ─── 中位数(50%) │ │ │ ┴ ─── 下四分位数 Q1(25%) │ ┴ ─── 最小值(下边缘) ○ ─── 异常值(离群点)

二、小提琴图 violinplot()——箱线图的升级版

小提琴图 = 箱线图 + 密度曲线。既能看到统计量,又能看到数据分布形状。

fig,axes=plt.subplots(1,2,figsize=(14,5))# --- 图1:基础小提琴图 ---vp=axes[0].violinplot(data,positions=[1,2,3,4],showmeans=True,showmedians=True)fori,bodyinenumerate(vp["bodies"]):body.set_facecolor(colors[i])body.set_alpha(0.7)axes[0].set_xticks([1,2,3,4])axes[0].set_xticklabels(labels)axes[0].set_ylabel("考试成绩",fontsize=12)axes[0].set_title("小提琴图",fontsize=14,fontweight="bold")axes[0].grid(True,alpha=0.3,axis="y")# --- 图2:箱线图 vs 小提琴图对比 ---# 同数据,一半箱线图一半小提琴图data_combined=np.concatenate(data)labels_combined=np.repeat(labels,[len(d)fordindata])axes[1].boxplot(data,labels=labels,patch_artist=True,widths=0.3,positions=np.arange(1,5)-0.15,showfliers=False)vp2=axes[1].violinplot(data,positions=np.arange(1,5)+0.15,showmedians=True)fori,bodyinenumerate(vp2["bodies"]):body.set_facecolor(colors[i])body.set_alpha(0.5)axes[1].set_xticks([1,2,3,4])axes[1].set_xticklabels(labels)axes[1].set_title("箱线图(左) + 小提琴图(右) 同框对比",fontsize=14,fontweight="bold")axes[1].grid(True,alpha=0.3,axis="y")plt.tight_layout()plt.show()

三、hexbin()——海量散点的高效可视化

普通散点图数据一多就糊成一片。hexbin()用六边形格子统计每个区域的数据密度。

np.random.seed(42)n=10000# 一万个点# 模拟有相关性的双变量数据mean=[0,0]cov=[[1,0.7],[0.7,1]]x,y=np.random.multivariate_normal(mean,cov,n).T fig,axes=plt.subplots(1,3,figsize=(16,5))# --- 普通散点图 ---axes[0].scatter(x,y,s=1,alpha=0.3,color="#5B9BD5")axes[0].set_title(f"普通散点图 (n={n})\n糊成一片")axes[0].set_xlabel("X")axes[0].set_ylabel("Y")axes[0].grid(True,alpha=0.3)# --- hexbin 六边形热力图 ---hb=axes[1].hexbin(x,y,gridsize=40,cmap="YlOrRd",mincnt=1)plt.colorbar(hb,ax=axes[1],label="数据点数",shrink=0.8)axes[1].set_title("hexbin 六边形密度图\n密度分布一目了然")axes[1].set_xlabel("X")axes[1].set_ylabel("Y")# --- 带等高线的 hexbin ---axes[2].hexbin(x,y,gridsize=40,cmap="Blues",mincnt=1)# 叠加 KDE 等高线(用 scipy)fromscipy.statsimportgaussian_kde kde=gaussian_kde(np.vstack([x,y]))xi,yi=np.mgrid[-4:4:100j,-4:4:100j]zi=kde(np.vstack([xi.flatten(),yi.flatten()])).reshape(xi.shape)axes[2].contour(xi,yi,zi,levels=6,colors="red",linewidths=1.5,alpha=0.7)axes[2].set_title("hexbin + KDE 等高线")axes[2].set_xlabel("X")axes[2].set_ylabel("Y")plt.tight_layout()plt.show()

四、3D 绘图入门

Matplotlib 可以画 3D 图,虽然不如专业工具强大,但日常够用。

# 导入 3D 模块frommpl_toolkits.mplot3dimportAxes3D# 虽未显式用但必须导入

4.1 3D 曲线

fig=plt.figure(figsize=(14,5))# --- 3D 螺旋线 ---ax1=fig.add_subplot(1,2,1,projection="3d")t=np.linspace(0,4*np.pi,200)x=np.sin(t)y=np.cos(t)z=t ax1.plot(x,y,z,"b-",linewidth=2)ax1.set_xlabel("X")ax1.set_ylabel("Y")ax1.set_zlabel("Z")ax1.set_title("3D 螺旋线",fontsize=12,fontweight="bold")# --- 3D 散点图 ---ax2=fig.add_subplot(1,2,2,projection="3d")np.random.seed(42)n=300xs=np.random.randn(n)ys=np.random.randn(n)zs=xs**2+ys**2+np.random.randn(n)*0.5sc=ax2.scatter(xs,ys,zs,c=zs,cmap="viridis",s=20,alpha=0.7)plt.colorbar(sc,ax=ax2,shrink=0.6,label="Z值")ax2.set_xlabel("X")ax2.set_ylabel("Y")ax2.set_zlabel("Z = X² + Y² + noise")ax2.set_title("3D 散点图",fontsize=12,fontweight="bold")plt.tight_layout()plt.show()

4.2 3D 曲面图

# 曲面图 plot_surfacex=np.linspace(-5,5,100)y=np.linspace(-5,5,100)X,Y=np.meshgrid(x,y)Z=np.sin(np.sqrt(X**2+Y**2))# 涟漪函数fig=plt.figure(figsize=(14,5))# --- 曲面图 ---ax1=fig.add_subplot(1,2,1,projection="3d")surf=ax1.plot_surface(X,Y,Z,cmap="viridis",alpha=0.85,linewidth=0,antialiased=True)plt.colorbar(surf,ax=ax1,shrink=0.6,label="Z值")ax1.set_xlabel("X")ax1.set_ylabel("Y")ax1.set_zlabel("Z")ax1.set_title("plot_surface 曲面图",fontsize=12,fontweight="bold")# --- 线框图 ---ax2=fig.add_subplot(1,2,2,projection="3d")ax2.plot_wireframe(X,Y,Z,rstride=5,cstride=5,color="steelblue",alpha=0.6,linewidth=0.5)ax2.set_xlabel("X")ax2.set_ylabel("Y")ax2.set_zlabel("Z")ax2.set_title("plot_wireframe 线框图",fontsize=12,fontweight="bold")plt.tight_layout()plt.show()

4.3 3D 柱状图

fig=plt.figure(figsize=(8,6))ax=fig.add_subplot(111,projection="3d")# 模拟 5天的4种产品销售数据days=np.arange(5)products=np.arange(4)data_3d=np.random.randint(10,100,(5,4))colors_3d=["#FF6B6B","#4ECDC4","#45B7D1","#FFEAA7"]_x=np.arange(5)# 天数_y=np.arange(4)# 产品_xx,_yy=np.meshgrid(_x,_y)x_flat,y_flat=_xx.ravel(),_yy.ravel()z_flat=np.zeros_like(x_flat)dx=dy=0.6dz=data_3d.T.ravel()# 每个柱子按产品颜色bar_colors=np.repeat(colors_3d,5)ax.bar3d(x_flat,y_flat,z_flat,dx,dy,dz,color=bar_colors,alpha=0.7,edgecolor="white")ax.set_xlabel("天数")ax.set_ylabel("产品")ax.set_zlabel("销量")ax.set_xticks(_x)ax.set_yticks(_y)ax.set_yticklabels(["手机","电脑","平板","耳机"])ax.set_title("3D 柱状图:5天 × 4产品",fontsize=14,fontweight="bold")plt.tight_layout()plt.show()

五、踩坑记录 🐛

现象解决方案
箱线图中文乱码标签出现方块确保 rcParams 字体设置在最前面
violinplot 位置偏移图和标签对不齐手动指定positions=[1,2,3...]
hexbin 颜色全一样密度差异看不出调整gridsize(越小格子越大,越容易区分)
3D 图交互卡顿旋转视角很慢减少数据点,或用rstride/cstride降低精度
3D 图视角不对默认角度看不清ax.view_init(elev=30, azim=45)调整仰角和方位角
scipy 未安装gaussian_kde 报错pip install scipy或跳过等高线部分

六、总结

图表类型函数一句话用途
箱线图boxplot()比较组间分布差异
小提琴图violinplot()看分布形状+统计量
六边形热力图hexbin()海量散点的密度分布
3D曲线plot()with projection=“3d”空间曲线
3D曲面plot_surface()函数z=f(x,y)可视化
3D柱状bar3d()三维数据对比

今天学完,Matplotlib 能画的图表类型你已经掌握了 90%。明天是 Matplotlib 的最终篇——综合实战,把前面 4 天的知识全部用在一个完整项目中。

第44天,打卡完成!📊


本系列是个人学习笔记,如有错误欢迎在评论区指正交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询