我正在尝试在python中绘制表面。我有一张N x 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.meshgrid
或numpy.mgrid
生成适当的X和Y 2D数组。编辑:
只是为了解释
mgrid
和meshgrid
的作用,让我们看一下它们的输出: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
的功能还有很多(它可能需要复杂的步骤参数来模仿linspace
,例如xx, yy = np.mgrid[0:1:10j, 0:5:5j]
将返回2个10x5数组,分别以0-1和0-5之间的数字递增),但让我们跳过ozt_code一秒钟。meshgrid
接受两个数组,并以类似于meshgrid
的方式对它们进行切片。举个例子: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]]))
mgrid
实际上恰好返回一个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()
关于python - 使用python进行3d绘图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8841827/