Python:有没有办法用Matplotlib绘制“部分”曲面图?

时间:2016-03-19 20:10:06

标签: python matplotlib

我想用Matplotlib绘制一个“部分”表面图,如下图所示 example

请注意,它不是X-Y平面上的完整网格网格,而是从顶视图中缺少一个角落。以下是我试过的代码,但没有用。

import numpy as np
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D

X = np.array([[0,1],
              [0,1,2],
              [0,1,2,3],
             ])
Y = np.array([[0,0],
              [1,1,1],
              [2,2,2,2],
             ])
Z = np.array([[0.5, 0.6],
              [0.7, 0.8, 0.9],
              [1.0, 1.1, 1.2, 1.3],
             ])
fig = pyplot.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X,Y,Z)

错误是:

  

ValueError:使用序列设置数组元素。

任何指针都会受到赞赏! 谢谢!

3 个答案:

答案 0 :(得分:6)

您可以在不想要绘制的区域中使用Z的np.nan值轻松完成此操作。这是this example的修改版本,但有剪切,如下所示:

enter image description here

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(.5*R)

Z[X+Y>4.] = np.nan  # the diagonal slice

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False, vmin=-1, vmax=1)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

另请注意,我必须在plot命令中使用vminvmax关键字,否则颜色缩放将被nans抛出。

答案 1 :(得分:1)

编辑:请看tom10的答案。他的解决方案通过将排除部分的值设置为np.nans来工作。

看起来matplotlib的plot_surface不接受np.nans作为坐标,所以这也不起作用。如果我正确理解你的问题,那么我至少要提供一个胶带解决方案:

如果不像MEVIS3000建议的那样将“切出”点设置为零,而是将它们设置为该维度中的最后一个值,那么您的2d阵列将具有相同的大小,并且表面看起来就像它在那里切割一样。

我为您的示例添加了更多数据点以使其更清晰。这是起点(整个表面可见的地方):

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


X = np.array([[0, 1, 2, 3, 4, 5],
              [0, 1, 2, 3, 4, 5],
              [0, 1, 2, 3, 4, 5],
             ])
Y = np.array([[0, 0, 0, 0, 0, 0],
              [1, 1, 1, 1, 1, 1],
              [2, 2, 2, 2, 2, 2],
             ])
Z = np.array([[0.5, 0.4, 0.35, 0.32, 0.312, 0.3],
              [0.9, 0.7, 0.60, 0.55, 0.525, 0.5],
              [1.0, 1.1, 1.20, 1.30, 1.400, 1.5],
             ])


fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X,Y,Z)

plt.show()

结果表面看起来像这样(从上面看): Pic 1: surface with original data

现在,如果我们调整数组以便将“缺失”值替换为该行中的先前值,我们可以省略表面的一部分:

X = np.array([[0, 1, 2, 2, 2, 2],  # Notice the sequence 0, 1, 2, 2, 2...
              [0, 1, 2, 3, 3, 3],  # Here starting from 3
              [0, 1, 2, 3, 4, 4],  # Here starting from 4
             ])
Y = np.array([[0, 0, 0, 0, 0, 0],  # Here we don't need to do anything
              [1, 1, 1, 1, 1, 1],
              [2, 2, 2, 2, 2, 2],
             ])
Z = np.array([[0.5, 0.4, 0.35, 0.35, 0.35, 0.35],  # Here like in X: repeats from 0.35
              [0.9, 0.7, 0.60, 0.55, 0.55, 0.55],
              [1.0, 1.1, 1.20, 1.30, 1.40, 1.40],
             ])

结果图表如下所示(同样来自同一视图): Pic 2: lower right corner cut out

这不是一个很好的解决方案,但它是一种方法。我将以某种方式让你自动解决“截止”问题。

答案 2 :(得分:0)

子阵列必须具有相同的长度。 e.g:

X = np.array([[0,1,0,0],
              [0,1,2,0],
              [0,1,2,3]
             ])

等等。