在 Python 中将第 4 个变量添加到 3D 图中 [英] Adding a 4th variable to a 3D plot in Python

查看:121
本文介绍了在 Python 中将第 4 个变量添加到 3D 图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个值范围内,我有3个不同的参数X,Y和Z,对于这些值的每种组合,它们都具有一定的V值.为了更加清楚,数据看起来像这样.

X Y Z V1 1 2 101 2 3 15等等...

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

非常感谢!

解决方案

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

I have 3 different parameters X,Y and Z over a range of values, and for each combination of these a certain value of V. To make it clearer, the data would look something like this.

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

I'd like to visualize the data with a surface/contour plot, using V as a colour to see its value at that point, but I do not see how to add my custom colouring scheme into the mix using Python. Any idea on how to do this (or is this visualization outright silly)?

Thanks a lot!

解决方案

Matplotlib allows one to pass the facecolors as an argument to e.g. ax.plot_surface.

That would imply then that you would have to perform 2D interpolation on your current array of colors, because you currently only have the colors in the corners of the rectangular faces (you did mention that you have a rectilinear grid).

You could use scipy.interpolate.interp2d for that, but as you see from the documentation, it is suggested to use scipy.interpolate.RectBivariateSpline.

To give you a simple example:

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

Now I have a similar dataset as you (one-dimensional arrays for x, y, z and colors). Remark that the colors are defined for each point (x,y). But when you want to plot with plot_surface, you'll generate rectangular patches, of which the corners are given by those points.

So, on to interpolation then:

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.

In this last step, you could also have used interp2d (with kind='linear' replacing the kx=1, ky=1). But since the docs suggest to use the faster RectBivariateSpline...

Now you're ready to plot it:

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

As you can see, the colors on the faces have nothing to do anymore with the height of the dataset.

Note that you could have thought simply passing the 2D array C to facecolors would work, and matplotlib would not have complained. However, the result isn't accurate then, because matplotlib will use only a subset of C for the facecolors (it seems to ignore the last column and last row of C). It is equivalent to using only the color defined by one coordinate (e.g. the top-left) over the entire patch.

An easier method would have been to let matplotlib do the interpolation and obtain the facecolors and then pass those in to the real plot:

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)

However, that won't work in releases <= 1.4.1 due to this recently submitted bug.

这篇关于在 Python 中将第 4 个变量添加到 3D 图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆