代码之家  ›  专栏  ›  技术社区  ›  bluey31

如何在matplotlib中以三维方式绘制3条等高线

  •  0
  • bluey31  · 技术社区  · 6 年前

    我有3条等高线,由以下内容生成:

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from scipy import stats
    
    mean0 = [ 3.1627717, 2.74815376]
    cov0  = [[0.44675818, -0.04885433], [-0.04885433, 0.52484173]]
    mean1 = [ 6.63373967, 6.82700035]
    cov1  = [[ 0.46269969, 0.11528141], [0.11528141, 0.50237073]]
    mean2 = [ 7.20726944, 2.61513787]
    cov2  = [[ 0.38486096, -0.13042758], [-0.13042758, 0.40928813]]
    
    x = np.linspace(0, 10, 100)
    y = np.linspace(0, 10, 100)
    X, Y = np.meshgrid(x, y)
    Z0 = np.random.random((len(x),len(y)))
    Z1 = np.random.random((len(x),len(y)))
    Z2 = np.random.random((len(x),len(y)))
    
    def pdf0(arg1,arg2):
        return (stats.multivariate_normal.pdf((arg1,arg2), mean0, cov0))
    def pdf1(arg1,arg2):
        return (stats.multivariate_normal.pdf((arg1,arg2), mean1, cov1))
    def pdf2(arg1,arg2):
        return (stats.multivariate_normal.pdf((arg1,arg2), mean2, cov2))
    
    
    for i in range (0, len(x)):
        for j in range(0,len(y)):
            Z0[i,j] = pdf0(x[i],y[j])
            Z1[i,j] = pdf1(x[i],y[j])
            Z2[i,j] = pdf2(x[i],y[j])
    
    Z0=Z0.T
    Z1=Z1.T        
    Z2=Z2.T
    
    fig3 = plt.figure()
    ax3 = fig3.add_subplot(111)
    ax3.contour(X,Y,Z0)
    ax3.contour(X,Y,Z1)
    ax3.contour(X,Y,Z2)
    plt.show()
    

    视觉上绘制如下:

    contours2d

    我希望在3D绘图中绘制所有这些内容,但当我尝试这样做时:

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1, projection='3d')
    
    # 3D plots for each contour.
    surf1 = ax.plot_surface(X, Y, Z0, cmap=cm.coolwarm, linewidth=0, antialiased=False)
    surf2 = ax.plot_surface(X, Y, Z1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
    surf3 = ax.plot_surface(X, Y, Z2, cmap=cm.coolwarm, linewidth=0, antialiased=False)
    
    ax.contour(X, Y, Z0, zdir='z', offset=-0.5)
    ax.contour(X, Y, Z1, zdir='z', offset=-0.5)
    ax.contour(X, Y, Z2, zdir='z', offset=-0.5)
    
    ax.set_zlim(-0.5, 0.31)
    
    plt.show()
    

    结果图如下所示:

    contours3d

    如何才能使其他两个3D轮廓很好地显示出来?

    1 回复  |  直到 6 年前
        1
  •  1
  •   ImportanceOfBeingErnest    6 年前

    这个问题没有通用的解决方案。Matplotlib无法决定将对象的一部分显示在比另一部分更前面的位置。参见例如 FAQ ,或其他问题,如 How to obscure a line behind a surface plot in matplotlib?

    如有必要,人们当然可以将物体分成几个部分。然而,在这里,将函数相加似乎就足够了。

    surf1 = ax.plot_surface(X, Y, Z0+Z1+Z2, cmap=plt.cm.coolwarm, 
                                            linewidth=0, antialiased=False)
    ax.contour(X, Y, Z0+Z1+Z2, zdir='z', offset=-0.5)
    

    enter image description here