如何在 matplotlib 中以 3D 形式绘制 3 个轮廓 [英] How do I plot 3 contours in 3D in matplotlib

查看:37
本文介绍了如何在 matplotlib 中以 3D 形式绘制 3 个轮廓的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 3 个轮廓,由以下生成:

将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt从 mpl_toolkits.mplot3d 导入 Axes3D来自 scipy 导入统计mean0 = [ 3.1627717, 2.74815376]cov0 = [[0.44675818, -0.04885433], [-0.04885433, 0.52484173]]平均值 1 = [ 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):返回(stats.multivariate_normal.pdf((arg1,arg2),mean0,cov0))def pdf1(arg1,arg2):返回(stats.multivariate_normal.pdf((arg1,arg2),mean1,cov1))def pdf2(arg1,arg2):返回(stats.multivariate_normal.pdf((arg1,arg2),mean2,cov2))对于范围内的 i (0, len(x)):对于范围内的 j (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.TZ1=Z1.TZ2=Z2.Tfig3 = plt.figure()ax3 = fig3.add_subplot(111)ax3.contour(X,Y,Z0)ax3.contour(X,Y,Z1)ax3.contour(X,Y,Z2)plt.show()

视觉上绘制如下:

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

fig = plt.figure()ax = fig.add_subplot(1, 1, 1, 投影='3d')# 每个轮廓的 3D 绘图.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()

结果图是这样的:

我怎样才能让另外两个 3D 轮廓很好地显示出来?

解决方案

这个问题没有通用的解决方案.Matplotlib 无法决定将对象的一部分显示在比另一部分更靠前的位置.见例如

I have 3 contours, generated by the following:

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()

Which, visually, is plotted as the following:

I am wishing to plot all of these in a 3D plot, but when I try do so with:

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()

The resulting graph is this:

How can I get the other two 3D contours to show nicely?

解决方案

There is no general solution to this problem. Matplotlib cannot decide to show part of an object more in front than another part of it. See e.g. the FAQ, or other questions, like How to obscure a line behind a surface plot in matplotlib?

One may of course split up the object in several parts if necessary. Here, however, it seems sufficient to add the functions up.

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)

这篇关于如何在 matplotlib 中以 3D 形式绘制 3 个轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆