python - 使用 facecolors 的 matplotlib plot_surface 的颜色条

标签 python matplotlib mplot3d

我正在尝试使用 facecolors 以预定义的颜色为表面着色 3D。这里的问题是 cm.ScalarMappable 规范化表面 V 的颜色,而 plt.cm.jet 不规范化,因此颜色和颜色条不匹配。我已经手动尝试规范化 V(即 V_normalized),但结果仍然不太正确。事实上,V 的最高值应该在曲面的一个角落,但这在实际图像中并没有体现出来。如何绘制以确保表面具有正确的颜色?

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# Create data.
X = np.array([[ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500],
              [ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500]])
Y = np.array([[ 75,  75,  75,  75,  75,  75,  75,  75,  75,  75],
               [125, 125, 125, 125, 125, 125, 125, 125, 125, 125],
               [175, 175, 175, 175, 175, 175, 175, 175, 175, 175],
               [225, 225, 225, 225, 225, 225, 225, 225, 225, 225],
               [275, 275, 275, 275, 275, 275, 275, 275, 275, 275],
               [325, 325, 325, 325, 325, 325, 325, 325, 325, 325],
               [375, 375, 375, 375, 375, 375, 375, 375, 375, 375],
               [425, 425, 425, 425, 425, 425, 425, 425, 425, 425],
               [475, 475, 475, 475, 475, 475, 475, 475, 475, 475]])
Z = pd.DataFrame([[2.11, 2.14, 2.12, 2.10, 2.09, 2.08, 2.07, 2.07, 2.08, 2.05],
                   [2.01, 2.03, 1.99, 1.96, 1.95, 1.93, 1.90, 1.90, 1.92, 1.92],
                   [1.89, 1.90, 1.90, 1.94, 1.92, 1.89, 1.88, 1.87, 1.86, 1.86],
                   [1.79, 1.79, 1.75, 1.79, 1.77, 1.78, 1.78, 1.78, 1.79, 1.76],
                   [1.75, 1.77, 1.8, 1.79, 1.8, 1.77, 1.73, 1.73, 1.77, 1.77],
                   [1.72, 1.76, 1.77, 1.77, 1.79, 1.8, 1.78, 1.78, 1.74, 1.7],
                   [1.67, 1.66, 1.69, 1.7, 1.65, 1.62, 1.63, 1.65, 1.7, 1.69],
                   [1.64, 1.64, 1.61, 1.59, 1.61, 1.67, 1.71, 1.7, 1.72, 1.69],
                   [1.63, 1.63, 1.62, 1.67, 1.7, 1.67, 1.67, 1.69, 1.69, 1.68]],
                 index=np.arange(75, 525, 50), columns=np.arange(50, 525, 50))
V = pd.DataFrame([[  7.53,   7.53,   7.53,   7.53,   7.53,   7.53,   7.53,   7.53, 7.53,   7.53],
       [  7.53,   7.53,   7.53,   7.53,   7.66,   8.09,   8.08,   8.05, 8.05,   8.05],
       [  7.53,   7.77,   8.08,   8.05,   8.19,   8.95,   8.93,   8.79,8.79,   8.62],
       [  8.95,   7.92,   8.95,   8.93,   8.62,   7.93,   8.96,   8.95, 9.09,   8.75],
       [  8.61,   8.95,   8.62,   8.61,   8.95,   8.93,   8.82,   9.42, 9.67,   8.48],
       [  9.23,   8.61,   8.95,   9.24,   9.42,   8.48,   8.47,   8.65, 8.92,   9.17],
       [  8.6 ,   9.01,   9.66,   8.05,   9.42,   8.92,   8.81,   7.53, 7.53,   7.53],
       [  9.42,   9.25,   8.65,   8.92,   8.25,   7.97,   8.09,   8.49, 8.49,   7.58],
       [ 10.15,   9.79,   9.1 ,   9.35,   9.35,   9.35,   9.25,   9.3 , 9.3 ,   8.19]],
                index=np.arange(75, 525, 50), columns=np.arange(50, 525, 50))
# Create the figure, add a 3d axis, set the viewing angle
# % matplotlib inline  # If you are using IPython
fig = plt.figure(figsize=[15,10])
ax = fig.add_subplot(111, projection='3d')
ax.view_init(45,60)
# Normalize in [0, 1] the DataFrame V that defines the color of the surface.
V_normalized = (V - V.min().min())
V_normalized = V_normalized / V_normalized.max().max()
# Plot
ax.plot_surface(X, Y, Z, facecolors=plt.cm.jet(V_normalized))
ax.set_xlabel('x', fontsize=18)
ax.set_ylabel('y', fontsize=18)
ax.set_zlabel('z', fontsize=18)
m = cm.ScalarMappable(cmap=cm.jet)
m.set_array(V)
plt.colorbar(m)

enter image description here

最佳答案

您的绘图是正确的,尽管您可以使用 matplotlib.colors.Normalize 实例简化归一化。

norm = matplotlib.colors.Normalize(vmin=V.min().min(), vmax=V.max().max())
ax.plot_surface(X, Y, Z, facecolors=plt.cm.jet(norm(V)))
m = cm.ScalarMappable(cmap=plt.cm.jet, norm=norm)
m.set_array([])
plt.colorbar(m)

在网格上看不到最大值 10.15 的原因是不同的:

当沿一维有 N 点时,绘图有 (N-1) 个面。这意味着输入颜色数组的最后一行和最后一列根本就没有被绘制出来。

这可以在下图中看到,其中绘制了一个 3x3 矩阵,得到 2x2 面。它们根据颜色数组中的相应值进行着色,这样第一个面的颜色由数组中的第一个元素给出,等等。对于最后一个元素,没有剩下要颜色的面。

enter image description here

重现此图的代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.colors

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = np.arange(3)
X,Y = np.meshgrid(x,x)
Z = np.ones_like(X)

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

norm = matplotlib.colors.Normalize(vmin=0, vmax=3)
ax.plot_surface(X, Y, Z, facecolors=plt.cm.jet(norm(V)), shade=False)

m = cm.ScalarMappable(cmap=plt.cm.jet, norm=norm)
m.set_array([])
plt.colorbar(m)

ax.set_xlabel('x')
ax.set_ylabel('y')

plt.show()

关于python - 使用 facecolors 的 matplotlib plot_surface 的颜色条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42924993/

相关文章:

python - 如何在 Python 中从极地立体图 grib2 文件绘制等高线

python - 创建一个以零为中心的白色颜色图

python - Python中Seaborn图上绘图的控制顺序

python - 如何生成 3D 时空轨迹图?

python - 扩展列表类以创建对象列表

python - django 1.8 - 'NoneType' 对象没有属性 'aggregate'

python - 如何使用人体姿势估计生成骨骼 View ?

python - Matplotlib xticks 未与直方图对齐

python - 在matplotlib trisurf 3d图python上反转y轴

python - 如何在 3D Matplotlib 散点图中为特定的网格线/刻度线着色?