所述matplotlib.pyplot.contour()
函数采用3个输入数组X
,Y
和Z
。
X
和Y
指定x和点的y坐标,而Z
指定所关注的点评价函数的对应值的阵列。
据我所知,np.meshgrid()
可以很容易地生产出作为参数传递给contour()
阵列:
X = np.arange(0,5,0.01)
Y = np.arange(0,3,0.01)
X_grid, Y_grid = np.meshgrid(X,Y)
Z_grid = X_grid**2 + Y_grid**2
plt.contour(X_grid, Y_grid, Z_grid) # Works fine
这工作得很好。和方便,这工作也没关系:
plt.contour(X, Y, Z_grid) # Works fine too
然而,为了是2D阵列为什么需要Z
输入?
为什么像下面不允许的,即使它指定了所有相同的数据适当对齐?
plt.contour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel()) # Disallowed
此外,什么是只指定Z
当语义(没有相应X
和Y
)?
看着the documentation of contour
一个发现,有一对夫妇的方式来调用这个函数,例如contour(Z)
或contour(X,Y,Z)
。所以,你会发现它不需要任何X
或Y
值是存在的。
然而,为了绘制轮廓,所述基础网格必须是已知的功能。 Matplotlib的contour
是基于矩形网格。但即便如此,允许contour(z)
,与z
是一维数组,就不可能知道现场应该如何绘制。在contour(Z)
的情况下Z
是2D阵列,其形状明确地将针对图中的网格。
一旦电网是已知的,它是相当不重要的可选X
和Y
阵列是否被平坦化与否;这实际上是个什么文件告诉我们:
X和Y必须都是2-d与相同形状的Z,或者它们必须都是1-d,使得LEN(X)是在Z和LEN(Y)的列数是在Z.的行数
这也是很明显的,像plt.contour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel())
成才不能产生一个等高线图,因为所有关于网格形状的信息丢失,没有办法轮廓功能可以知道如何interprete数据。例如。如果len(Z_grid.ravel()) == 12
,底层网格的形状可以是任何(1,12), (2,6), (3,4), (4,3), (6,2), (12,1)
的。
一个可能的出路当然可以允许一维数组,并介绍参数shape
,像plt.contour(x,y,z, shape=(6,2))
。然而,这是不是这样的,所以你要住在一起Z
需要为2D的事实。
但是,如果你正在寻找一种方式来获得与扁平(弄明白)阵列的等高线图,这是可能的使用qazxsw POI。
plt.tricontour()
这里,三角格子将在内部使用的Delaunay Triangualation来制造。因此,即使完全随机点会产生一个很好的结果,如下面的图片,在这相对于给plt.tricontour(X_grid.ravel(), Y_grid.ravel(), Z_grid.ravel())
相同的随机点可以看出。
contour
后面code to produce this picture算法的实际代码可以在plt.contour
找到。这是相当复杂的C代码,所以难以遵循它精确,但如果我试图做出一些轮廓生成代码,我会做下列方式。选择一些点_countour.cpp在边境和修复其(x, y)
价值。遍历附近的点,挑选一个针对z值最接近的第一点的z值。继续对新点迭代,挑附近的点与z值最接近所需(但检查你不还给你刚刚去过的一个点,所以你必须在一些“方向”走),并继续下去,直到你得到一个周期或达到某些边界。
这似乎是一个接近(但稍微复杂一些)的z
实现。
当你从算法的非正式描述看,继续,你必须找到一个点,这是“附近”,以目前的一个。这是很容易,如果你有点的矩形网格办(需要约4或8次迭代是这样的:_counter.cpp
,(x[i+1][j], y[i+1][j])
,(x[i][j+1], y[i][j+1])
等)。但是,如果你有一些随机选取的点(没有任何特定的顺序),这个问题变得很困难:你必须遍历所有你必须要找到那些附近,使下一步的点。这样步骤(x[i-1][j], y[i-1][j])
complexity,其中is是多个点(典型地为一个大小的图像的的平方)的O(n)
。因此,一个算法,如果你没有一个矩形网格变得慢得多。
这就是为什么你的实际需要三个二维阵列对应于x的,Y的并且位于一些矩形网格一些点的个Z。
当你正确提到,n
的和x
的可能是一维数组。在这种情况下,对应的2D阵列被重建与y
。然而,在这种情况下,你必须有meshgrid
为二维阵列反正。
如果只指定z
是,z
和x
是适当长度y
的。
编辑。你可以尝试这样的方式“假”二维range
,x
和y
阵列是z
和x
没有形成一个矩形网格检查,如果我的假设是正确的。
y
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
x = np.random.uniform(-3, 3, size=10000)
y = np.random.uniform(-3, 3, size=10000)
z = x**2 + y**2
X, Y, Z = (u.reshape(100, 100) for u in (x, y, z))
plt.contour(X, Y, Z)
正如你看到的,画面看起来并不像任何接近正确的图形,如果(X,Y,Z)的只是一些随机点。
现在让我们假设为@dhrummel建议在评论认为排序作为预处理步骤。请注意,我们不能排序x
和x
同时放,因为它们不是独立的(我们要保留的相同点)。
y
x = np.random.uniform(-3, 3, size=10000)
y = np.random.uniform(-3, 3, size=10000)
z = x**2 + y**2
xyz = np.array([x, y, z]).T
x, y, z = xyz[xyz[:, 0].argsort()].T
assert (x == np.sort(x)).all()
X, Y, Z = (u.reshape(100, 100) for u in (x, y, z))
plt.contour(X, Y, Z)
为2D的原因,X和Y如下。 ž匹配到每个(X,Y)中的轴系统坐标对应的“深度”,以创建具有x,y和z坐标的三维曲线图。
现在假设我们想指出的轴系统内的任意一点。我们可以做到这一点通过本point.For例如(0,0)提供的X和Y坐标(X,Y)。现在考虑的“行”与x值1.在这一行有一个数n y值的,它看起来像水木清华:
y
如果我们绘制该行对于所有的x值和y的值,我们会得到不便。喜欢:
正如你可以看到,我们有其由2个2D阵列,一个用于具有所述形状的x值的2D注释:
,一个用于具有所述形状的y值:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
#--> Two dimensional x values array
这两个一起提供(X,Y)坐标的坐标系内的每个点。现在,我们就可以绘制每个点的“深度”指的Z值(Z坐标)。现在它也是显而易见的,为什么在Z变量必须是2维与形状(LEN(x)中,LEN(Y)),因为否则就不能提供所有点的值。
提供1D x和y阵列的功能和功能在内部创建从x和与不便y值的二维网格:可以通过提供2D的x,y,和z阵列功能或实现此行为。如X,Y = np.meshgrid(X,Y),但仍然Ž必须是二维的。
让我以简单的方式解释,因为我认为ž不应该是2D为好。 10 10 10 10 10 10 10 10 10 10
9 9 9 9 9 9 9 9 9 9
8 8 8 8 8 8 8 8 8 8
...
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
#--> Two dimensional y values array
需要X和Y建立自己的空间,关系Z(X,Y),构建一个完整的空间,而不是仅仅使用几个百分点1D X,Y,Z的信息。
试想一下,你要绘制三维图形。有一组contourf()
点和一组x
点。我们的目标是产生用于每对y
和z
的值x
,或换句话说,你需要一个函数y
这样就产生f
的值,使得z
。
这里是(从MathWorks公司获取)一个很好的例子:
该z = f(x, y)
和x
坐标是在底部右侧和底部分别离开。你将有一个功能y
使得对于每对f
和x
,我们生成一个y
值。因此,在你提供的代码中,z
通话将产生两个二维数组,从而为每一个独特的空间位置,我们将观察numpy.meshgrid
和x
值是唯一的那个位置。
例如,让我们用一个非常小的例子:
y
看一看行号2和列号1例如(我从0开始的索引顺便说一句)。这意味着,在这个空间位置,我们将协调In [1]: import numpy as np
In [2]: x, y = np.meshgrid(np.linspace(-1, 1, 3), np.linspace(-1, 1, 3))
In [3]: x
Out[3]:
array([[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]])
In [4]: y
Out[4]:
array([[-1., -1., -1.],
[ 0., 0., 0.],
[ 1., 1., 1.]])
和x = 0.
。 y = 1
给了我们需要产生numpy.meshgrid
的在该特定的值坐标x
和y
对。它只是分成为了方便两个2D阵列。
现在什么终于把你z
变量是,它应该使用功能z
并处理输出是做什么用的f
和每个值及其相应x
。
明确地说,你需要制定一个y
数组,它是2D这样的:
z
在z = [f(-1, -1) f(0, -1) f(1, -1)]
[f(-1, 0) f(0, 0) f(1, 0)]
[f(-1, 1) f(0, 1) f(1, 1)]
和x
方面的空间布置非常仔细地看。我们会为每对y
和x
值的9个唯一值。所述y
值从-1到1,并且在同一对x
跨越。一旦你生成这个y
二维数组,你可以使用z
绘制出水平集,使每个轮廓线会给你一套等于contourf
的相同值的所有可能的x
和y
值。另外,在各相邻对不同线之间,我们用相同的颜色填充的区域在两者之间。
让我们结束这关有一个实际的例子。假设我们有功能z
。这是一个二维高斯f(x, y) = exp(-(x**2 + y**2) / 10)
的标准偏差。
因此,让我们产生sqrt(5)
和x
值的网格,用它来生成y
值,绘制出z
情节:
contourf
我们得到:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 101)
y = x
x, y = np.meshgrid(x, y)
z = np.exp(-(x**2 + y**2) / 10)
fig,ax2 = plt.subplots(1)
ax2.contourf(x,y,z)
plt.show()