繁体   English   中英

用python 3d绘图

[英]3d plotting with python

我正在尝试在python中绘制表面。 我有N×N值的表格。 我创建了两个向量X和Y,每个元素N个。 当我尝试绘制此图时,出现错误:

ValueError: total size of new array must be unchanged

我检查了示例,然后看到对于Z的N个元素,对于X和Y有N个元素。

这对我来说毫无意义。 我为什么需要N个元素而不是N个N个?

这是一个示例代码:

导入随机导入数学

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

bignum = 100

mat = []
X = []
Y = []

for x in range(0,bignum):
    mat.append([])
    X.append(x);
    for y in range (0,bignum):
        mat[x].append(random.random())
        Y.append(y)

fig = plt.figure(figsize=plt.figaspect(2.))
ax = fig.add_subplot(1,1,1, projection='3d')
surf = ax.plot_surface(X,Y,mat)

首先,永远不要做这样的事情:

mat = []
X = []
Y = []

for x in range(0,bignum):
    mat.append([])
    X.append(x);
    for y in range (0,bignum):
        mat[x].append(random.random())
        Y.append(y)

这等效于:

mat = np.random.random((bignum, bignum))
X, Y = np.mgrid[:bignum, :bignum]

...但是速度快了几个数量级,并且使用的内存只有使用列表然后转换为数组的一部分。

但是,您的示例效果很好。

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

bignum = 100
mat = np.random.random((bignum, bignum))
X, Y = np.mgrid[:bignum, :bignum]

fig = plt.figure()
ax = fig.add_subplot(1,1,1, projection='3d')
surf = ax.plot_surface(X,Y,mat)
plt.show()

在此处输入图片说明

如果您阅读了plot_surface的文档,则可以清楚地看到X,Y和Z应该是2D数组。

这样,您就可以通过固有地定义点之间的连通性来绘制更复杂的曲面(例如球体)。 (例如,从matplotlib画廊中看到以下示例: http : //matplotlib.sourceforge.net/examples/mplot3d/surface3d_demo2.html

如果您具有一维X和Y数组,并且希望从2D网格中获得一个简单的曲面,请使用numpy.meshgridnumpy.mgrid生成适当的X和Y 2D数组。

编辑:只是为了解释mgridmeshgrid作用,让我们看一下它们的输出:

print np.mgrid[:5, :5]

产量:

array([[[0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2],
        [3, 3, 3, 3, 3],
        [4, 4, 4, 4, 4]],

       [[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]]])

因此,它返回形状为2x5x5的单个3D数组,但将其更容易地视为两个2D数组。 一个代表5x5网格上任何点的i坐标,而另一个代表j坐标。

由于python解压缩的工作方式,我们可以这样写:

xx, yy = np.mgrid[:5, :5]

Python并不在乎mgrid返回什么,它只会尝试将其分解为两个项目。 因为numpy数组会在其第一个轴的切片上进行迭代,所以如果解压缩形状为(2x5x5)的数组,我们将得到2个,5x5数组。 同样,我们可以执行以下操作:

xx, yy, zz = np.mgrid[:5, :5, :5]

...并获得3个3D 5x5x5索引阵列。 另外,如果我们用不同的范围切片(例如xx, yy = np.mgrid[10:15, 3:8] ,它将平铺索引从10到14(含)和3到7(含)。

mgrid还有很多其他功能(它可能需要复杂的step参数来模拟linspace ,例如xx, yy = np.mgrid[0:1:10j, 0:5:5j]将返回2个10x5数组,其数字在0- 1和0-5),但让我们跳到meshgrid一秒钟。

meshgrid接受两个数组,并以与mgrid类似的方式将它们平铺。 举个例子:

x = np.arange(5)
y = np.arange(5)
xx, yy = np.meshgrid(x, y)
print xx, yy

产量:

(array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]]), 

array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4]]))

meshgrid实际上碰巧返回了2个,5x5 2D数组的元组,但是区别并不重要。 关键区别在于指标不必在特定方向上增加。 它只是平铺给定的数组。 举个例子:

x = [0.1, 2.4, -5, 19]
y = [-4.3, 2, -1, 18.4]
xx, yy = np.meshgrid(x, y)

产量:

(array([[  0.1,   2.4,  -5. ,  19. ],
       [  0.1,   2.4,  -5. ,  19. ],
       [  0.1,   2.4,  -5. ,  19. ],
       [  0.1,   2.4,  -5. ,  19. ]]),
 array([[ -4.3,  -4.3,  -4.3,  -4.3],
       [  2. ,   2. ,   2. ,   2. ],
       [ -1. ,  -1. ,  -1. ,  -1. ],
       [ 18.4,  18.4,  18.4,  18.4]]))

您会注意到,它只是平铺了我们提供的值。

基本上,当您需要使用与输入网格相同形状的索引时,可以使用它们。 当您要根据网格值评估函数时,它最有用。

例如

import numpy as np
import matplotlib.pyplot as plt

x, y = np.mgrid[-10:10, -10:10]
dist = np.hypot(x, y) # Linear distance from point 0, 0
z = np.cos(2 * dist / np.pi)

plt.title(r'$\cos(\frac{2*\sqrt{x^2 + y^2}}{\pi})$', size=20)
plt.imshow(z, origin='lower', interpolation='bicubic',
          extent=(x.min(), x.max(), y.min(), y.max()))
plt.colorbar()
plt.show()

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM