布局格式定乾坤
1. 子图
1.1 使用 plt.subplots 绘制均匀状态下的子图
subplots 的函数格式如下:
fig , ax = plt.subplots(nrows, ncols)
nrows 与 ncols 表示两个整数参数,它们指定子图所占的行数、列数。不传入时默认值都为1。figsize 参数可以指定整个画布的大小,sharex 和 sharey 分别表示是否共享横轴和纵轴刻度,tight_layout 函数可以调整子图的相对大小使字符不会重叠。函数的返回值是一个元组,包括一个图形对象和所有的 axes 对象。其中 axes 对象的数量等于 nrows * ncols,且每个 axes 对象均可通过索引值访问(从1开始)。
import numpy as np
import matplotlib.pyplot as plt
fig,axs=plt.subplots(2,5,figsize=(10,4),sharex=True,sharey=True)
fig.suptitle('样例1',size=20)
for i in range(2):
for j in range(5):
axs[i][j].scatter(np.random.randn(10),np.random.randn(10))
axs[i][j].set_title('第%d行,第%d列'%(i+1,j+1))
axs[i][j].set_xlim(-5,5)
axs[i][j].set_ylim(-5,5)
if i==1:
axs[i][j].set_xlabel('横坐标')
if j==0:
axs[i][j].set_ylabel('纵坐标')
fig.tight_layout()

subplot() 函数可以均等地划分画布,该函数的参数格式如下:
plt.subplot(nrows, ncols, index)
nrows 与 ncols 表示要划分几行几列的子区域(nrows*nclos表示子图数量),index 的初始值为1,用来选定具体的某个子区域。
plt.figure()
# 子图1
plt.subplot(2,2,1)
plt.plot([1,2],'r')
# 子图2
plt.subplot(2,2,2)
plt.plot([1,2],'b')
# 子图3
plt.subplot(224) # 当三位数都小于10时,可以省略中间的逗号,这行命令等价于plt.subplot(2,2,4)
plt.plot([1,2],'m')
plt.show()

可以通过projection方法创建极坐标系下的图表
# 极坐标
N=150
r=2*np.random.rand(N)
theta=2*np.pi*np.random.rand(N)
area=200*r**2
colors=theta
plt.subplot(projection='polar')
plt.scatter(theta,r,c=colors,s=area,cmap='hsv',alpha=0.75)
plt.show()

1.2 使用 GridSpac 绘制非均匀子图
所谓非均匀包含两层含义,第一是指图的比例大小不同但没有跨行或跨列,第二是指图为跨列或跨行状态。
利用 add_gridspec 可以指定相对宽度比例 width_ratios 和相对高度比例参数 height_ratios。
# 使用GridSpec 绘制非均匀子图
fig=plt.figure(figsize=(10,4))
spec=fig.add_gridspec(nrows=2,ncols=5,width_ratios=[1,2,3,4,5],height_ratios=[1,3])
fig.suptitle('样例2',size=20)
for i in range(2):
for j in range(5):
ax=fig.add_subplot(spec[i,j])
ax.scatter(np.random.randn(10),np.random.randn(10))
ax.set_title('第%d行,第%d列'%(i+1,j+1))
if i==1: ax.set_xlabel('横坐标')
if j==0: ax.set_ylabel('纵坐标')
fig.tight_layout()

fig=plt.figure(figsize=(10,4))
spec=fig.add_gridspec(nrows=2,ncols=6,width_ratios=[2,2.5,3,1,1.5,2],height_ratios=[1,2])
fig.suptitle('样例3',size=20)
#sub1
ax=fig.add_subplot(spec[0,:3])
ax.scatter(np.random.randn(10),np.random.randn(10))
#sub2
ax=fig.add_subplot(spec[0,3:5])
ax.scatter(np.random.randn(10),np.random.randn(10))
#sub3
ax=fig.add_subplot(spec[:,5])
ax.scatter(np.random.randn(10),np.random.randn(10))
#sub4
ax=fig.add_subplot(spec[1,0])
ax.scatter(np.random.randn(10),np.random.randn(10))
#sub5
ax=fig.add_subplot(spec[1,1:5])
ax.scatter(np.random.randn(10),np.random.randn(10))
fig.tight_layout()

2. 子图上的方法
常用直线的画法为: axhline, axvline, axline (水平、垂直、任意方向)
fig,ax=plt.subplots(figsize=(4,3))
ax.axhline(0.5,0.2,0.8)
ax.axvline(0.5,0.2,0.8)
ax.axline([0.3,0.3],[0.7,0.7]);

使用 grid 可以加灰色网格
fig,ax=plt.subplots(figsize=(4,3))
ax.grid(True)

思考题
- 墨尔本1981年至1990年的每月温度情况。数据集来自github仓库下data/layout_ex1.csv,请利用数据,画出图。
- 画出数据的散点图和边际分布。
# 读取数据
import pandas as pd
path='./layout_ex1.csv'
dg=pd.read_csv(path)
dg.head()

dg['Year']=pd.to_datetime(dg['Time']).dt.year
dg['Month']=pd.to_datetime(dg['Time']).dt.month
fig,axes=plt.subplots(2,5,figsize=(25,6),sharex=True,sharey=True)
fig.suptitle('墨尔本1981年至1990年月温度曲线')
t=0
g=0
for i,j in dg.groupby('Year'):
if t<=4:
axes[0][t].set_title('{}年'.format(i),size=12)
axes[0][t].plot(j['Month'],j['Temperature'],'cD-')
axes[0][t].grid(True)
t+=1
else:
axes[1][g].set_title('{}年'.format(i),size=10)
axes[1][g].plot(j['Month'],j['Temperature'],'yo:')
axes[1][g].set_xticks(range(1,13))
axes[1][g].grid(True)
g+=1

- 用 np.random.randn(2, 150) 生成一组二维数据,使用两种非均匀子图的分割方法,做出该数据对应的散点图和边际分布图
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
data=np.random.randn(2, 150)
fig = plt.figure()
spec = gridspec.GridSpec(nrows=6, ncols=6, width_ratios=[1,1,1,1,1,1], height_ratios=[1,1,1,1,1,1])
#子图1
ax=fig.add_subplot(spec[0,:5])
ax.hist(data[0,:],bins=10,rwidth=0.8,color='y',alpha=0.5)
for i in ['right','left','top','bottom']:
ax.spines[i].set_visible(False) #边框不可见
ax.get_xaxis().set_visible(False) # x轴不可见
ax.get_yaxis().set_visible(False) # y轴不可见
#子图3
ax=fig.add_subplot(spec[1:,:5])
area=200*np.random.rand(150)
ax.scatter(data[0,:],data[1,:],c='m',marker='o',s=area,alpha=0.75)
ax.grid(True)
ax.set_xlabel('my_data_x')
ax.set_ylabel('my_data_y')
#子图4
ax=fig.add_subplot(spec[1:,5:6])
ax.hist(data[1,:],orientation='horizontal',bins=10,rwidth=0.8,color='y',alpha=0.5)
for i in ['right','left','top','bottom']:
ax.spines[i].set_visible(False)
ax.get_xaxis().set_visible(False) # x轴不可见
ax.get_yaxis().set_visible(False) # y轴不可见
plt.tight_layout()

本文详细介绍了使用Python的Matplotlib库创建和定制子图的方法,包括使用`subplots`和`GridSpec`进行均匀和非均匀子图布局,以及在子图上添加各种图形元素。示例代码涵盖了散点图、直方图和极坐标图的绘制,同时展示了如何调整子图的大小和位置以避免字符重叠。此外,还展示了如何利用数据生成散点图和边际分布图。

被折叠的 条评论
为什么被折叠?



