使用 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 中绘制轮廓图,我将 x
和 y
坐标划分为 X,Y = meshgrid(x,y)
,但 z
数组也必须是二维数组。然后如何将 z
转换为二维数组以便使用?
你的z
错了。它需要给出网格每个点的值。如果 z
是 x
和 y
的函数,计算 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 表面的情况下,这仍然是一个相关问题。
三个一维数组的等高线绘图选项
基本就三种选择
- 使用tricontourf to draw it, if you don't absolutely have to use the regular contourf函数。适用于网格化和非网格化数据。
- 如果你的数据是网格化的,但是在三个独立的一维数组中,你可以将它们分成两个一维数组和一个二维数组,并用[=19=绘制它们]
- 如果您的数据未网格化,并且您不想使用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.DataFrame
df
作为中间媒介。
- 然后,使用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)
)
如标题所示,我想使用三个一维数组绘制等高线图。比方说
x = np.array([1,2,3])
和
y = np.array([1,2,3])
和
z = np.array([20,21,45])
为了在 matplotlib 中绘制轮廓图,我将 x
和 y
坐标划分为 X,Y = meshgrid(x,y)
,但 z
数组也必须是二维数组。然后如何将 z
转换为二维数组以便使用?
你的z
错了。它需要给出网格每个点的值。如果 z
是 x
和 y
的函数,计算 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 表面的情况下,这仍然是一个相关问题。
三个一维数组的等高线绘图选项
基本就三种选择
- 使用tricontourf to draw it, if you don't absolutely have to use the regular contourf函数。适用于网格化和非网格化数据。
- 如果你的数据是网格化的,但是在三个独立的一维数组中,你可以将它们分成两个一维数组和一个二维数组,并用[=19=绘制它们]
- 如果您的数据未网格化,并且您不想使用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.DataFrame
df
作为中间媒介。 - 然后,使用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)
)