为什么pyplot.contour()要求Z到是一个二维数组?

问题描述 投票:11回答:5

所述matplotlib.pyplot.contour()函数采用3个输入数组XYZXY指定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当语义(没有相应XY)?

python numpy matplotlib contour
5个回答
9
投票

看着the documentation of contour一个发现,有一对夫妇的方式来调用这个函数,例如contour(Z)contour(X,Y,Z)。所以,你会发现它不需要任何XY值是存在的。

然而,为了绘制轮廓,所述基础网格必须是已知的功能。 Matplotlib的contour是基于矩形网格。但即便如此,允许contour(z),与z是一维数组,就不可能知道现场应该如何绘制。在contour(Z)的情况下Z是2D阵列,其形状明确地将针对图中的网格。

一旦电网是已知的,它是相当不重要的可选XY阵列是否被平坦化与否;这实际上是个什么文件告诉我们:

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

(这里是enter image description here


3
投票

后面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是,zx是适当长度y的。

编辑。你可以尝试这样的方式“假”二维rangexy阵列是zx没有形成一个矩形网格检查,如果我的假设是正确的。

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建议在评论认为Incorrect result排序作为预处理步骤。请注意,我们不能排序xx同时放,因为它们不是独立的(我们要保留的相同点)。

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)

同样,图片是不正确,因为事实上,x is sorted now的不排序(按照每列),因为他们如果我们有矩形网格而不是一些随机点。


2
投票

为2D的原因,X和Y如下。 ž匹配到每个(X,Y)中的轴系统坐标对应的“深度”,以创建具有x,y和z坐标的三维曲线图。

现在假设我们想指出的轴系统内的任意一点。我们可以做到这一点通过本point.For例如(0,0)提供的X和Y坐标(X,Y)。现在考虑的“行”与x值1.在这一行有一个数n y值的,它看起来像水木清华:

y

如果我们绘制该行对于所有的x值和y的值,我们会得到不便。喜欢:

enter image description here

正如你可以看到,我们有其由2个2D阵列,一个用于具有所述形状的x值的2D注释:

enter image description here

,一个用于具有所述形状的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),但仍然Ž必须是二维的。


0
投票

让我以简单的方式解释,因为我认为ž不应该是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的信息。


0
投票

试想一下,你要绘制三维图形。有一组contourf()点和一组x点。我们的目标是产生用于每对yz的值x,或换句话说,你需要一个函数y这样就产生f的值,使得z

这里是(从MathWorks公司获取)一个很好的例子:

z = f(x, y)x坐标是在底部右侧和底部分别离开。你将有一个功能y使得对于每对fx,我们生成一个y值。因此,在你提供的代码中,z通话将产生两个二维数组,从而为每一个独特的空间位置,我们将观察numpy.meshgridx值是唯一的那个位置。

例如,让我们用一个非常小的例子:

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的在该特定的值坐标xy对。它只是分成为了方便两个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方面的空间布置非常仔细地看。我们会为每对yx值的9个唯一值。所述y值从-1到1,并且在同一对x跨越。一旦你生成这个y二维数组,你可以使用z绘制出水平集,使每个轮廓线会给你一套等于contourf的相同值的所有可能的xy值。另外,在各相邻对不同线之间,我们用相同的颜色填充的区域在两者之间。

让我们结束这关有一个实际的例子。假设我们有功能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()

© www.soinside.com 2019 - 2024. All rights reserved.