使用 python 中的三个一维数组绘制等高线图

Make a contour plot by using three 1D arrays in python

如标题所示,我想使用三个一维数组绘制等高线图。比方说

x = np.array([1,2,3])

y = np.array([1,2,3])

z = np.array([20,21,45])

为了在 matplotlib 中绘制轮廓图,我将 xy 坐标划分为 X,Y = meshgrid(x,y),但 z 数组也必须是二维数组。然后如何将 z 转换为二维数组以便使用?

你的z错了。它需要给出网格每个点的值。如果 zxy 的函数,计算 z 在我下面称为 X_grid 的地方:

import numpy as np
import matplotlib.pyplot as plt

def f(x):
    return (x[:,0]**2 + x[:,1]**2)

x = np.array([1,2,3])
y = np.array([1,2,3])
xx, yy = np.meshgrid(x, y)
X_grid = np.c_[ np.ravel(xx), np.ravel(yy) ]
z = f(X_grid)

z = z.reshape(xx.shape)

plt.contour(xx, yy, z)

在我看来,您描述的是通过 space 的 one-dimensional 曲线而不是曲面。我这么说是因为我假设 x[i]y[i]z[i] 是一个点的坐标。您不能使用这些点以简单的方式定义曲面,因为您的点仅取决于一个变量 i,因此仅描述具有一个自由度的形状。考虑到您可以将列表中的每个点连接到下一个,并且这只会给您一个一维的点链。为了用三个阵列制作一个表面,您必须定义 9 个 z 值,而不是 3 个。

很抱歉,这不是一个有用的答案,但我没有 post 发表评论的名誉。

如果我使用为了更容易操作而拼凑的数据,我经常会遇到这个问题。在分解数据中,二维数组被展平。

原始数据每个坐标都有x、y、z值:

x = [0, 1, 2; 0, 1, 2]

y = [0, 0, 0; 1, 1, 1]

z = [0.1 , 0.2, 0.3 ; 0.2, 0.3, 0.4]

对所有三个数组使用 np.ravel() 使它们成为一维 6 元素长数组。

xx = np.ravel(x); yy = np.ravel(y) ; zz = np.ravel(z)

现在 xx = ([0, 1, 2, 0, 1, 2]),对于 yy 和 zz 也是如此。

如果这是您正在处理的数据类型并且数据经过彻底采样,您可以使用散点图模拟 contourf 图。这仅在您的数据集采样足够好以填充所有 space.

时才有效
plt.scatter(xx,yy,c=zz,cmap=cm.Reds)

尽管 OP 意识到不可能用问题中的数据绘制等高线图,但在可以将数据视为 3d 表面的情况下,这仍然是一个相关问题。

三个一维数组的等高线绘图选项

基本就三种选择

  1. 使用tricontourf to draw it, if you don't absolutely have to use the regular contourf函数。适用于网格化和非网格化数据。
  2. 如果你的数据是网格化的,但是在三个独立的一维数组中,你可以将它们分成两个一维数组和一个二维数组,并用[=19=绘制它们]
  3. 如果您的数据未网格化,并且您不想使用tricontourf,您可以将数据插值到网格中,然后用 contourf 绘制它。 许多 3d 插值问题 可以帮助您解决这个问题。对数据进行插值后,您可以使用选项 2 中显示的技术。

选项 1:tricontourf

这个超级简单。只需像这样使用 plt.tricontourf 函数(参见附录中示例数据的创建)

from matplotlib import pyplot as plt

plt.tricontourf(xdata, ydata, zdata)
plt.show()

输出

选项 2:网格化一维数组和 contourf

如果 网格数据存储在三个一维数组 中,并且出于某种原因不想使用 tricontourf,那么您可以如何制作 contourf密谋出来。 (附录中给出的示例数据)

import pandas as pd
from matplotlib import pyplot as plt 

df = pd.DataFrame(dict(x=xdata, y=ydata, z=zdata))
xcol, ycol, zcol = "x", "y", "z"
df = df.sort_values(by=[xcol, ycol])
xvals = df[xcol].unique()
yvals = df[ycol].unique()
zvals = df[zcol].values.reshape(len(xvals), len(yvals)).T
plt.contourf(xvals, yvals, zvals)
plt.show()

输出

想法解释

  • 首先,必须对数据进行网格化,因为这就是 plt.contour 图的工作原理。如果不是,您可以将其插入到新网格中。
  • 然后,创建pandas.DataFramedf作为中间媒介。
  • 然后,使用df.sort_values()方法对x和y数据进行排序。这使得 unique() 给出的值在下一步中排序。
  • 使用 unique() 获取 x 和 y 数据的所有唯一值。这是一种与“网格”操作相反的操作。
  • 由于 pandas 数据框列的值只是 numpy 数组,您可以调用 reshape() 方法来创建所需的二维数组。
  • 现在如果 x 有 N 个唯一值,y 有 M 个唯一值,那么 zvals 将是一个 (N,M) 二维数组,可以馈送到 plt.contour.

附录:示例数据

import numpy as np
import pandas as pd

xs, ys = np.linspace(-4, 4), np.linspace(-4, 4)
xgrid, ygrid = np.meshgrid(xs, ys)
xdata, ydata = np.ravel(xgrid), np.ravel(ygrid)
zdata = (
    2.3 * (1 - xdata) ** 2 * np.exp(-(ydata ** 2) - (xdata + 0.9) ** 2)
    - 13.3
    * (ydata / 2.2 - ydata ** 3 - xdata ** 4)
    * np.exp(-(ydata ** 2) - xdata ** 2)
    - 0.8 * np.exp(-((ydata + 1) ** 2) - xdata ** 2)
)