让3d Python plot像Matlab一样漂亮

Make 3d Python plot as beautiful as Matlab

注: 这不是转换问题。目的是看看Python是否有能力像Matlab一样制作3D绘图。

我创建了一个 Matlab 绘图,如下所示:

我尝试使用 Python 绘制它,但我无法像 Matlab 那样好。有没有什么包可以把上面的图画的和原来的一样好?如果是,请将我的代码转换为 Python 版本。这是我的 Matlab 代码。

set(groot,'defaultAxesTickLabelInterpreter','latex');  
set(groot,'defaulttextinterpreter','latex');
set(groot,'defaultLegendInterpreter','latex');
x0=0;
y0=0;
width=3000;
height=2000;
set(gcf,'position',[x0,y0,width,height])
[X,Y] = meshgrid(-1:.01:1);
a = 3;
b = 2;
Z = a*X.^2 + b*Y.^2;
subplot(1,3,1)
s = surf(X,Y,Z,'FaceColor','r', 'FaceAlpha',0.5, 'EdgeColor','none');
s.EdgeColor = 'none';
xlabel('$x_1$','Interpreter','latex','FontSize', 15)
ylabel('$x_2$','Interpreter','latex','FontSize', 15)
zlabel('$f(\mathbf{x};\mathbf{\theta})$','Interpreter','latex','FontSize', 15)
legend({'$f([x_1, x_2]^\top; [\theta_1=3,\theta_2=2]^\top)=3x_1^2+2x_2^2$'},'interpreter','latex','FontSize', 10)
subplot(1,3,2)
Z2 = a*X.^2 ;
s2 = surf(X,Y,Z2,'FaceColor','b', 'FaceAlpha',0.5, 'EdgeColor','none');
s2.EdgeColor = 'none';
xlabel('$x_1$','Interpreter','latex','FontSize', 15)
ylabel('$x_2$','Interpreter','latex','FontSize', 15)
zlabel('$f(\mathbf{x};\mathbf{\theta})$','Interpreter','latex','FontSize', 15)
legend({'$f([x_1, x_2]^\top; [\theta_1=3,\theta_2=0]^\top)=3x_1^2$'},'interpreter','latex','FontSize', 10)
subplot(1,3,3)
s3 = surf(X,Y,Z,'FaceColor','r', 'FaceAlpha',0.5, 'EdgeColor','none');
s3.EdgeColor = 'none';
hold
s4 = surf(X,Y,Z2,'FaceColor','b', 'FaceAlpha',0.5, 'EdgeColor','none');
s4.EdgeColor = 'none';
xlabel('$x_1$','Interpreter','latex','FontSize', 15)
ylabel('$x_2$','Interpreter','latex','FontSize', 15)
zlabel('$f(\mathbf{x};\mathbf{\theta})$','Interpreter','latex','FontSize', 15)
legend({'$f(\mathbf{x};\mathbf{\theta})=3x_1^2+2x_2^2$', '$f(\mathbf{x};\mathbf{\theta})=3x_1^2$'},'interpreter','latex','FontSize', 10)

对于 Python 中的 3D 图表,我在 matplotlib.pyplot 中获得了最好的结果。

#!/usr/bin/python3 
# -*- coding: utf-8 -*-   
import matplotlib.pyplot as plt  
from mpl_toolkits.mplot3d.axes3d import Axes3D, get_test_data  
from matplotlib import cm   
import numpy as np   
import random  
X_k_list = range(1, 100, 10)  
Y_p_list = [ float(x)/100.0 for x in range(1, 100, 10) ]   
# set up a figure twice as wide as it is tall  
fig = plt.figure(figsize=plt.figaspect(0.5))  
# set up the axes for the first plot  
ax = fig.add_subplot(1, 1, 1, projection='3d')  
# plot a 3D surface like in the example mplot3d/surface3d_demo  
X, Y = np.meshgrid(X_k_list, Y_p_list)  
def critical_function(b, c):  
    num = random.uniform(0, 1) * 10.0  
    return num + (b * c)   
  
Z_accuracy = X.copy()  
Z_accuracy = Z_accuracy.astype(np.float32)  
for i in range(len(X_k_list)):  
    for j in range(len(Y_p_list)):  
        Z_accuracy[j][i] = critical_function(Y_p_list[j], X_k_list[i])  
  
surf = ax.plot_surface(X, Y, Z_accuracy,   
    rstride=1, cstride=1, cmap=cm.coolwarm,  
    linewidth=0, antialiased=False)  
  
ax.set_xlabel('X')  
ax.set_ylabel('Y')  
ax.set_zlabel('Z')  
fig.colorbar(surf, shrink=0.5, aspect=10)  
plt.show()  

https://www.python-graph-gallery.com/371-surface-plot

您可以通过添加更多数据点来增加图表的平滑度,使用鼠标沿 x、y、z 轴旋转图表,还可以添加标题、图例和其他吸引眼球的东西。

matplotlib.mplot3d 看起来像欧几里德连续曲面

#!/usr/bin/python3 
# -*- coding: utf-8 -*- 
from mpl_toolkits.mplot3d import axes3d 
import matplotlib.pyplot as plt 
from matplotlib import cm 
ax = plt.figure().add_subplot(projection='3d') 
X, Y, Z = axes3d.get_test_data(0.05) 
cset = ax.contour(X, Y, Z, extend3d=True, cmap=cm.coolwarm) 
ax.clabel(cset, fontsize=9, inline=True) 
plt.show() 

https://matplotlib.org/stable/gallery/mplot3d/contour3d_2.html#sphx-glr-gallery-mplot3d-contour3d-2-py

您正在使用 matlab 的 meshgrid(...) 工具生成 x,y,z 数据。 Python 可以达到与 numpy.meshgrid 相同的结果,因此输入 matplotlib.pyplot

#!/usr/bin/python3 
# -*- coding: utf-8 -*- 
import numpy as np 
import matplotlib.pyplot as plt 
def f(x, y): 
    return np.sin(np.sqrt(x ** 2 + y ** 2)) 
x = np.linspace(-6, 6, 30) 
y = np.linspace(-6, 6, 30) 
X, Y = np.meshgrid(x, y) 
Z = f(X, Y) 
fig = plt.figure() 
ax = plt.axes(projection='3d') 
ax.contour3D(X, Y, Z, 50, cmap='binary') 
ax.set_xlabel('x') 
ax.set_ylabel('y') 
ax.set_zlabel('z') 
plt.show() 

https://jakevdp.github.io/PythonDataScienceHandbook/04.12-three-dimensional-plotting.html

是的。

numpy + plotly 是一种有效的 Matlab 替代品——您可能认识一些代码 :)。作为一个好处,这些图呈现为 html,这意味着它们具有高度可移植性,保存为单个文件,并且可以嵌入到网页中。可能有不同的小细节(我不知道乳胶轴标签的当前状态),但是,如果您安装了 python、numpy 和 plotly,以下是您第一个图的一个很好的替代品:

import plotly.graph_objects as go
import numpy as np

x = np.arange(-1,1,.01)
y = np.arange(-1,1,.01)
X,Y = np.meshgrid(x,y)
a = 3
b = 2
Z = a*X**2 + b*Y**2

fig = go.Figure(
    data=[go.Surface(z=Z, x=x, y=y, colorscale="Reds", opacity=0.5)])
fig.update_layout(
    title='My title', 
    autosize=False,
    width=500, 
    height=500,
    margin=dict(l=65, r=50, b=65, t=90), 
    scene_aspectmode='cube'
)
fig.show()

请注意,python 中的首选绘图包是 Matplotlib。 IMO,它继承了 Matlab 绘图的所有最差部分和 none 好的部分(性能渲染)。从性能(尤其是 3D 渲染)、交互性和 API 的角度来看非常出色。