python用matplotlib 画3维图(坐标、刻度、网格、图例设置)
直接画出的三维图坐标、网格等不太好看,总结了很多自定义的方法
首先获得数据,画出最基本的三维图
pdf = scio.loadmat(SRC_DIR1 + 'pdf.mat')
pdf_updating = pdf['y_l']/10
N = np.array(pdf_updating).shape[0]
truth_l = np.arange(0, 150, 1)
T_l = []
z = []
t_l = np.ones(150)
for i in range(1, 85):
T_l.append(t_l*i-1)
z.append(0)
fig = plt.figure(figsize=(4, 3), dpi=300)
ax = fig.add_subplot(111, projection='3d')
# PDF
for i in range(N):
if i == 5:
ax.plot(T_l[i], truth_l, pdf_updating[i][:150], color='b', lw=0.5, label='line1')
x = np.linspace(84, 1, 84)
y = np.linspace(1, 84, 84)
x_n = []
y_n = []
for i in range(len(x)):
if i % 6 == 0:
x_n.append(x[i])
y_n.append(y[i])
ax.plot(y_n, x_n, 0, color='r', lw=0.5, linestyle='-', marker='x', markersize='3', markeredgewidth=0.8,
label='line2')
这样画出来的的三维图网格和背景都是灰色的不好看通过网格设置将网格线改为黑色虚线;网格背景改为白色。并把Z轴移动到左边。
# 设置网格线形
ax.xaxis._axinfo["grid"].update({"linewidth": 0.3, "linestyle": '--', "color": 'k'})
ax.yaxis._axinfo["grid"].update({"linewidth": 0.3, "linestyle": '--', "color": 'k'})
ax.zaxis._axinfo["grid"].update({"linewidth": 0.3, "linestyle": '--', "color": 'k'})
# 设置网格背景色
ax.w_xaxis.set_pane_color((0, 0, 0, 0))
ax.w_yaxis.set_pane_color((0, 0, 0, 0))
ax.w_zaxis.set_pane_color((0, 0, 0, 0))
# 更改z轴位置
ax.zaxis._axinfo['juggled'] = (1, 2, 7)
设置坐标轴线宽
# 设置坐标轴线宽
ax.w_xaxis.line.set_lw(0.6)
ax.w_yaxis.line.set_lw(0.6)
ax.w_zaxis.line.set_lw(0.6)
刻度相关设置
# 刻度设置
ax.tick_params(axis='z', labelsize=5, pad=-3, direction='in')
ax.tick_params(axis='x', labelsize=5, pad=-5, direction='in')
ax.tick_params(axis='y', labelsize=5, pad=-5, direction='in')
ax.xaxis._axinfo['tick']['outward_factor'] = 0
ax.xaxis._axinfo['tick']['inward_factor'] = 0.4
ax.yaxis._axinfo['tick']['outward_factor'] = 0
ax.yaxis._axinfo['tick']['inward_factor'] = 0.4
ax.zaxis._axinfo['tick']['outward_factor'] = 0.4
ax.zaxis._axinfo['tick']['inward_factor'] = 0.0
# 刻度间隔
x0 = MultipleLocator(20) # x轴每10一个刻度
y0 = MultipleLocator(30)
z0 = MultipleLocator(0.005)
ax.xaxis.set_major_locator(x0)
ax.yaxis.set_major_locator(y0)
ax.zaxis.set_major_locator(z0)
设置一下坐标轴的显示范围,再给图添加个框线
# 坐标轴范围
ax.set_xlim([84, 0]) # 调换了x轴的大小
ax.set_ylim([0.0, 150])
# 添加框线
add_borders(ax, edgecolor=(0, 0, 0, 1), linewidth=0.3) # 添加边框
def add_borders(ax, edgecolor=(0, 0, 0, 1), linewidth=0.57, scale=1.021):
xlims = ax.get_xlim3d()
xoffset = (xlims[1] - xlims[0]) * scale
xlims = np.array([xlims[1] - xoffset, xlims[0] + xoffset])
ylims = ax.get_ylim3d()
yoffset = (ylims[1] - ylims[0]) * scale
ylims = np.array([ylims[1] - yoffset, ylims[0] + yoffset])
zlims = ax.get_zlim3d()
zoffset = (zlims[1] - zlims[0]) * scale
zlims = np.array([zlims[1] - zoffset, zlims[0] + zoffset])
verts1 = np.array([[xlims[0], ylims[1], zlims[1]],
[xlims[0], ylims[0], zlims[1]]])
verts2 = np.array([[xlims[0], ylims[1], zlims[1]],
[xlims[1], ylims[1], zlims[1]]])
verts3 = np.array([[xlims[1], ylims[1], zlims[0]],
[xlims[1], ylims[1], zlims[1]]])
p = art3d.Line3DCollection([verts1, verts2, verts3], colors=edgecolor, linewidths=linewidth, linestyles='--')
ax.add_collection3d(p)
return True
给坐标轴命名
# 坐标轴名称
font = {'size': 5, 'family': 'SimHei', 'weight': 'normal'}
ax.set_xlabel('x', labelpad=-10, fontdict=font, rotation=-25,)
ax.set_ylabel('y', labelpad=-10, rotation=30, fontdict=font)
ax.set_zlabel('z', labelpad=-10, rotation=90, fontdict=font)
转换一下视场,添加图例
# 转换视角
ax.view_init(22, -45)
# 添加图例
plt.legend(prop=legend_font, bbox_to_anchor=(0.85, 0.75), frameon=False)
plt.show()