【问题标题】:Adding a 4th variable to a 3D plot in Python在 Python 中将第四个变量添加到 3D 图中
【发布时间】:2015-02-04 15:03:46
【问题描述】:

我有 3 个不同的参数 X、Y 和 Z 在一个值范围内,并且对于这些的每个组合都有一个特定的 V 值。为了更清楚,数据看起来像这样。

X  Y  Z  V
1  1  2  10
1  2  3  15
etc...

我想用表面/等高线图可视化数据,使用 V 作为颜色来查看其在该点的值,但我不知道如何使用 Python 将我的自定义着色方案添加到混合中。关于如何做到这一点的任何想法(或者这种可视化完全愚蠢)?

非常感谢!

【问题讨论】:

标签: python matplotlib plot mayavi 4d


【解决方案1】:

Matplotlib 允许将 facecolors 作为参数传递给例如 ax.plot_surface.

这意味着您必须在您的 当前的颜色数组,因为您目前只有 矩形面的角(你确实提到你有一个直线 网格)。

你可以使用 scipy.interpolate.interp2d 为此,但正如您从文档中看到的那样,建议使用 scipy.interpolate.RectBivariateSpline.

举个简单的例子:

import numpy as np
y,x = np.mgrid[1:10:10j, 1:10:10j] # returns 2D arrays
# You have 1D arrays that would make a rectangular grid if properly reshaped.
y,x = y.ravel(), x.ravel()  # so let's convert to 1D arrays
z = x*(x-y)
colors = np.cos(x**2) - np.sin(y)**2

现在我有一个和你类似的数据集(x, y, zcolors)。备注颜色是为 每个点 (x,y)。但是当你想用plot_surface 绘图时,你会 生成矩形块,其中的角由这些点给出。

那么,接着插值:

from scipy.interpolate import RectBivariateSpline
# from scipy.interpolate import interp2d # could 've used this too, but docs suggest the faster RectBivariateSpline

# Define the points at the centers of the faces:
y_coords, x_coords = np.unique(y), np.unique(x)
y_centers, x_centers = [ arr[:-1] + np.diff(arr)/2 for arr in (y_coords, x_coords)]

# Convert back to a 2D grid, required for plot_surface:
Y = y.reshape(y_coords.size, -1)
X = x.reshape(-1, x_coords.size)
Z = z.reshape(X.shape)
C = colors.reshape(X.shape)
#Normalize the colors to fit in the range 0-1, ready for using in the colormap:
C -= C.min()
C /= C.max()

interp_func = RectBivariateSpline(x_coords, y_coords, C.T, kx=1, ky=1) # the kx, ky define the order of interpolation. Keep it simple, use linear interpolation.

在最后一步中,您还可以使用interp2d(与kind='linear' 替换kx=1, ky=1)。但是由于文档建议使用更快的 RectBivariateSpline...

现在您可以绘制它了:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.cm as cm

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
r = ax.plot_surface(X,Y,Z,
    facecolors=cm.hot(interp_func(x_centers, y_centers).T),
    rstride=1,  cstride=1) # only added because of this very limited dataset

如您所见,脸上的颜色与数据集的高度无关。

请注意,您可能认为只需将 2D 数组 C 传递给 facecolors 即可,而 matplotlib 不会抱怨。但是,结果并不准确,因为 matplotlib 将仅使用 C 的一个子集作为面部颜色(它似乎忽略了 C 的最后一列和最后一行)。这相当于在整个补丁上仅使用一个坐标(例如左上角)定义的颜色。

一个更简单的方法是让 matplotlib 进行插值并获得面部颜色,然后将它们传递给真实的情节:

r = ax.plot_surface(X,Y,C, cmap='hot') # first plot the 2nd dataset, i.e. the colors
fc = r.get_facecolors()
ax.clear()
ax.plot_surface(X, Y, Z, facecolors=fc)

但是,由于this recently submitted bug,这在版本

【讨论】:

    【解决方案2】:

    这实际上取决于您计划如何绘制这些数据。我喜欢用gnuplot 绘制图表:它简单、免费且直观。要使用gnuplot 绘制示例,您必须将这些行打印到文件中(只有这四列)并使用如下代码进行绘制

     reset
     set terminal png
     set output "out.png"
     splot "file.txt" using 1:2:3:4 with lines palette
    

    假设您将数据保存到文件file.txtsplot 代表曲面图。当然,这是一个最小的例子。

    您也可以使用matplotlib,但在我看来,这并不直观。虽然它的优点是把所有的处理都集中在python中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-14
      • 2021-09-11
      • 2018-07-08
      • 2020-06-26
      • 2021-11-24
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多