3d绘图与python

Yot*_*tam 11 python plot numpy matplotlib

我正在尝试在python中绘制曲面.我有一个N乘N值的表.我已经创建了N个元素的两个向量X和Y. 当我试图绘制这个时,我收到一个错误:

ValueError: total size of new array must be unchanged
Run Code Online (Sandbox Code Playgroud)

我查看了这些例子,我看到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)
Run Code Online (Sandbox Code Playgroud)

Joe*_*ton 20

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

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)
Run Code Online (Sandbox Code Playgroud)

这相当于:

mat = np.random.random((bignum, bignum))
X, Y = np.mgrid[:bignum, :bignum]
Run Code Online (Sandbox Code Playgroud)

...但它的速度要快几个数量级,并使用一小部分内存,使用列表然后转换为数组.

但是,您的示例完美无缺.

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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果你阅读文档plot_surface,它清楚地说X,Y和Z应该是2D数组.

这样您就可以通过固有地定义点之间的连接来绘制更复杂的曲面(例如球体).(例如,请参阅matplotlib图库中的此示例:http://matplotlib.sourceforge.net/examples/mplot3d/surface3d_demo2.html)

如果您有1D X和Y阵列,并且想要2D网格中的简单曲面,则使用numpy.meshgridnumpy.mgrid生成适当的X和Y 2D阵列.

编辑: 只是为了解释什么mgridmeshgrid做,让我们来看看他们的输出:

print np.mgrid[:5, :5]
Run Code Online (Sandbox Code Playgroud)

收益率:

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]]])
Run Code Online (Sandbox Code Playgroud)

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

由于python的解包方式有效,我们可以写:

xx, yy = np.mgrid[:5, :5]
Run Code Online (Sandbox Code Playgroud)

Python并不关心究竟mgrid返回什么,它只会尝试将其解压缩为两个项目.因为numpy数组迭代它们的第一个轴的切片,所以如果我们解压缩形状为(2x5x5)的数组,我们将得到2,5x5数组.同样,我们可以做以下事情:

xx, yy, zz = np.mgrid[:5, :5, :5]
Run Code Online (Sandbox Code Playgroud)

...并获得3个3D 5x5x5阵列的标记.此外,如果我们使用不同的范围进行切片(例如,xx, yy = np.mgrid[10:15, 3:8]它会将标记从10到14(包括)和3到7(包括)).

还有一点mgrid(模拟可能需要复杂的步骤参数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
Run Code Online (Sandbox Code Playgroud)

收益率:

(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]]))
Run Code Online (Sandbox Code Playgroud)

meshgrid实际上恰好返回2个5x5 2D数组的元组,但这种区别并不重要.关键的区别在于,指标不必在特定方向上增加.它只是对给定的数组进行切片.举个例子:

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

收益率:

(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]]))
Run Code Online (Sandbox Code Playgroud)

正如您将注意到的那样,它只是平铺了我们给它的值.

基本上,当您需要处理与输入网格形状相同的指标时,可以使用这些.当您想要评估网格值上的函数时,它非常有用.

例如

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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • Joe你是完全正确的,但如果`X.append(x)`在第二个循环中被移动,那么它将在示例中起作用.如果你有一个NxN长的一维数组,`plot_surface`仍然有效.错误是说matplotlib无法重塑1D阵列,因此它是N×N 2D阵列.你也太快了. (2认同)