繁体   English   中英

如何在颜色条上绘制散点图?

[英]How to plot scatter plot points on a colorbar?

我有一个评估函数的简单曲面图,我使用它在 3d 中绘制

surf = ax.plot_surface(xx, yy, zz)

对于 x、y 和 z 轴。

使用 surf 对象,我还创建了一个颜色条

fig.colorbar(surf, shrink=0.5, aspect=5)

然后我用一个简单的散点函数在曲面图上绘制点

plot = ax.scatter(xs=[], ys=[], zs=[], c="black", alpha=1.0, zorder=50)

这很好用,我得到了一个很好的曲面图,上面画了点。 我还在它旁边看到一个颜色条,显示评估函数梯度。

我现在想绘制与散点图相同的点,但在颜色条上。 这样,我想显示点与所需值的接近程度。 我已经搜索了一段时间的文档,但我对 matplotlib 很陌生,所以我不知道如何操作颜色条以显示点。 如果你能帮我在颜色条上的一个随机位置画一个点,那么我会从那里拿它。

不确定这是否是您要查找的内容。

我改编了本教程中的示例并选择了 20 个随机点。 这些点分散在表面上。 并且它们的 z 值绘制在颜色条上。 为了不在一条直线上显示所有值,随机的 x 坐标用于在颜色条中定位。

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

surf = ax.plot_surface(X, Y, Z, cmap=plt.cm.coolwarm,
                       linewidth=0, antialiased=True)

ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

cbar = fig.colorbar(surf, shrink=0.8, aspect=8)

num_selected = 20
selection = (np.random.randint(0, 40, num_selected), np.random.randint(0, 40, num_selected))
plot = ax.scatter(xs=X[selection], ys=Y[selection], zs=Z[selection], c="black", alpha=1.0, zorder=50)
cbar.ax.scatter(x=np.random.uniform(*cbar.ax.set_xlim(), num_selected), y=Z[selection], c='k', s=5)
plt.show()

示例图

是的,可以在colorbar上绘图。 您只需要重新调整数据。

让我们生成一些带有点的表面,我将模拟优化器(随机优化器)并在表面上绘制其步骤:

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d


def zfun(x, y):
    """For computing Z"""
    return x * np.cos(x) - y * np.cos(y)


# reproducibility first
np.random.seed(2020)

# Get some data
# define Space
X = np.linspace(-5, 5, 20)
Y = np.linspace(-5, 5, 20)
X, Y = np.meshgrid(X, Y)
Z = zfun(X, Y)

# Prepare fig
fw, fh = 10, 5
view = (65, 30)
fig = plt.figure(figsize=(fw, fh))
ax = fig.add_subplot(111, projection='3d')
ax.view_init(view[0], view[-1])

# Plot surface
surf = ax.plot_surface(X, Y, Z, cmap='jet', zorder=-1)

# Here is our test points: optimizer steps a kind of :)
x = np.random.choice(np.arange(-3, 3, 0.25), 7)
y = np.random.choice(np.arange(-5, 5, 0.25), 7)
z = zfun(x, y)

# I use plot3D, I think in 3D space it does better than scatter
# And you can connect all the dots to get a line
ax.plot3D(x, y, z, 'o-', c='k', markersize=5, zorder=3)
# Put a starting point
ax.plot3D([x[0]], [y[0]], [z[0]], 'o', c='r', markersize=5, zorder=3)
# Put the end
ax.plot3D([x[-1]], [y[-1]], [z[-1]], 'o', c='b', markersize=5, zorder=3)

# get some bars
cb = fig.colorbar(surf)

阴谋:

cbar0

我们需要一把ax在上面画图。 幸好colorbar有这个功能:

print('ax' in dir(cb))

出去:

True

但是它有自己的 y 和 x 限制,它们的计算方式对我来说仍然是一个魔术,但似乎它们是由 z 最小值和最大值定义的,我们可以使用get_xlim()get_ylim()方法查看它们:

print('cbar xlimits:', cb.ax.get_xlim())
print('cbar ylimits:', cb.ax.get_ylim())
print('Z min, max:', Z.min(), Z.max())

出去:

cbar xlimits: (-6.095315696318178, 6.095315696318178)
cbar ylimits: (-6.095315696318178, 6.095315696318178)
Z min, max: -6.5766626168117845 6.5766626168117845

因此,如果您想将 ath 放在颜色条上,则需要重新缩放它。 我们将使用这个函数:

def rescale(arr, min_=0, max_=1):
    scale = (max_ - min_) / (arr.max() - arr.min())
    arr = arr * scale + min_ - arr.min() * scale
    return arr

现在我们可以在颜色条上绘图。 让我们首先绘制迭代顺序:

...
cb = fig.colorbar(surf)
# we need this line now
cb.ax.set_aspect('auto')
# Put some labels
cb.ax.set_xlabel('iteration ->')
cb.ax.set_ylabel('z')

# get vals for rescale function
min_, max_ = cb.ax.get_xlim()

# generate and iter sequence [0, 1, 2, 3...]
iters = np.arange(len(z))
# rescale it
iters = rescale(iters, min_, max_)

# Now plot it!
cb.ax.scatter(iters, z, s=50, c='k', edgecolor='w')  # add points
cb.ax.plot(iters, z, '--', c='k')  # add line
cb.ax.plot(iters[0], z[0], 'o', c='r', markersize=5, label='start')
cb.ax.plot(iters[-1], z[-1], 'o', c='b', markersize=5, label='end')
cb.ax.legend()

阴谋:

cbar1

您还可以在 cbar 上绘制 x 和 y 值,您只需要重新缩放它。 这是 cbar 的 x 轴上的 x 值和 y 轴上的 z 值:

...
cb = fig.colorbar(surf)
# we need this line now
cb.ax.set_aspect('auto')
# Put some labels
cb.ax.set_xlabel('x')
cb.ax.set_ylabel('z')

# get vals for rescale function
min_, max_ = cb.ax.get_xlim()

# rescale
x = rescale(x, min_, max_)

cb.ax.scatter(x, z, s=50, c='k', edgecolor='w')  # add points
cb.ax.plot(x, z, '--', c='k')  # add line
cb.ax.plot(x[0], z[0], 'o', c='r', markersize=5, label='start')
cb.ax.plot(x[-1], z[-1], 'o', c='b', markersize=5, label='end')
cb.ax.legend()

阴谋:

cbar2

与 y:

阴谋:

cbar3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM