如何将固定颜色条添加到 3D 散点动画图并相应地对点进行颜色映射?

Posted

技术标签:

【中文标题】如何将固定颜色条添加到 3D 散点动画图并相应地对点进行颜色映射?【英文标题】:How could I add fixed color bar to a 3D scatter animated plot and color map the points accordingly? 【发布时间】:2021-07-24 20:57:15 【问题描述】:

我花了相当多的时间阅读了很多关于如何生成动画散点图以及如何对它们进行颜色编码的帖子。理想情况下,我希望有 X、Y、Z 坐标的散点图,每个都有一个根据它们对应的 M 值的大小和一个根据它们对应的 t 值的颜色。颜色代码必须从一开始就根据向量 t 的最大和最小时间固定,并且点以与其时间值(即 t 向量)相关联的颜色出现。文章的最后一部分(最后的代码)能够根据M生成不同大小但只有一种颜色的散点图。

更多细节:关于数据集,我有每个点的 X、Y、Z 坐标,每个事件点都分配了一个值 (M),每个事件都发生在特定时间 (t) . 我让每个点的大小与它们的值成正比(即 M),现在我想为每个点添加颜色,以便它也显示发生的时间。

解决方案 (1) 我试过了: 我知道我必须使用 .set_color(c)c 值需要一个元组值。我试图标准化时间值以映射来自this post 的颜色。但是,我错过了一些东西,因为代码无法为相关时间的点着色。我使用了以下代码

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
from IPython.display import html # Animation on jupyter lab 
from matplotlib.animation import PillowWriter # For GIF animation 
#####Data Generation####

# Space Coordinate
X = np.random.random((100,)) * 255 * 2 - 255
Y = np.random.random((100,)) * 255 * 2 - 255
Z = np.random.random((100,)) * 255 * 2 - 255

# Magnitude of each point
# M = np.random.random((100,))*-1+0.5
M = np.random.randint(1,70, size=100)
# Time
t = np.sort(np.random.random((100,))*10)



x = []
y = []
z = []
m = []
cmap = plt.cm.Spectral
norm = plt.Normalize(vmin=min(t), vmax=max(t))
# plt.scatter(x,y, c = cmap(norm(t)))
def update_lines(i):
#     for i in range (df_IS["EASTING [m]"].size):
    dx = X[i]
    dy = Y[i]
    dz = Z[i]
    dm = M[i]
#     text.set_text(":d: [:.0f] Mw[:.2f]".format(ID[i], t[i],ID[i]))  # for debugging
    x.append(dx) 
    y.append(dy) 
    z.append(dz)
    m.append(dm)
    graph._offsets3d = (x, y, z)
    graph.set_sizes(m)
    return graph,

fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(X, Y, Z, s=M, c = cmap(norm(t)))  # s argument here 
text = fig.text(0, 1, "TEXT", va='top')  # for debugging

ax.set_xlim3d(X.min(), X.max())
ax.set_ylim3d(Y.min(), Y.max())
ax.set_zlim3d(Z.min(), Z.max())

# Creating the Animation object
ani = animation.FuncAnimation(fig, update_lines, frames=30, interval=500, blit=False, repeat=False)
# plt.show()
ani.save('test3Dscatter.gif', writer='pillow')
plt.close()
HTML(ani.to_html5_video())

解决方案(2)我试过了:我还研究了this post,基于我添加的这篇帖子:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
from IPython.display import HTML # Animation on jupyter lab 
from matplotlib.animation import PillowWriter # For GIF animation 
#####Data Generation####
X = np.random.random((100,)) * 255 * 2 - 255
Y = np.random.random((100,)) * 255 * 2 - 255
Z = np.random.random((100,)) * 255 * 2 - 255

# Magnitude of each point
# M = np.random.random((100,))*-1+0.5
M = np.random.randint(1,70, size=100)
# Time
t = np.sort(np.random.random((100,))*10)


x = []
y = []
z = []
m = []
t = []
###=====edited part=====####
def get_colour(t): 
    '''
    with this function I tried to generate a new color for each point and then use the graph.set- 
    color to plot it but it is not successful
    '''
    cmap = matplotlib.cm.get_cmap('Spectral');
    return cmap(t);

def update_lines(i):
#     for i in range (df_IS["EASTING [m]"].size):
    dx = X[i]
    dy = Y[i]
    dz = Z[i]
    dm = M[i]
    dt = t[i]
    #     text.set_text(":d: [:.0f] Mw[:.2f]".format(ID[i], t[i],ID[i]))  # for debugging
    x.append(dx) 
    y.append(dy) 
    z.append(dz)
    m.append(dm)
    t.append(dt)
    graph._offsets3d = (x, y, z)
    graph.set_sizes(m)
    graph.set_color(c=get_colour(t))
    return graph,

如果有人能分享他们的经验,我将不胜感激,看看我如何将颜色条和颜色映射点添加到图表中? 这是生成不同大小但颜色统一的 3D 散点图的代码。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
from IPython.display import HTML # Animation on jupyter lab 
from matplotlib.animation import PillowWriter # For GIF animation 
#####Data Generation####

# Space Coordinate
X = np.random.random((100,)) * 255 * 2 - 255
Y = np.random.random((100,)) * 255 * 2 - 255
Z = np.random.random((100,)) * 255 * 2 - 255

# Magnitude of each point
# M = np.random.random((100,))*-1+0.5
M = np.random.randint(1,70, size=100)
# Time
t = np.sort(np.random.random((100,))*10)

#ID each point should be color coded. Moreover, each point belongs to a cluster `ID`
ID = np.sort(np.round([np.random.random((100,))*5]))

x = []
y = []
z = []
m = []

def update_lines(i):
#     for i in range (df_IS["EASTING [m]"].size):
    dx = X[i]
    dy = Y[i]
    dz = Z[i]
    dm = M[i]
#     text.set_text(":d: [:.0f] Mw[:.2f]".format(ID[i], t[i],ID[i]))  # for debugging
    x.append(dx) 
    y.append(dy) 
    z.append(dz)
    m.append(dm)
    graph._offsets3d = (x, y, z)
    graph.set_sizes(m)
    return graph,

fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(X, Y, Z, s=M, color='orange')  # s argument here 
text = fig.text(0, 1, "TEXT", va='top')  # for debugging

ax.set_xlim3d(X.min(), X.max())
ax.set_ylim3d(Y.min(), Y.max())
ax.set_zlim3d(Z.min(), Z.max())

# Creating the Animation object
ani = animation.FuncAnimation(fig, update_lines, frames=30, interval=500, blit=False, repeat=False)
# plt.show()
ani.save('test3Dscatter.gif', writer='pillow')
plt.close()
HTML(ani.to_html5_video())

【问题讨论】:

【参考方案1】:
frame    = ax.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
cbar     = fig.colorbar(frame) 

更多详情请参考此链接: How to animate the colorbar in matplotlib

【讨论】:

以上是关于如何将固定颜色条添加到 3D 散点动画图并相应地对点进行颜色映射?的主要内容,如果未能解决你的问题,请参考以下文章

Excel 添加散点图并添加趋势线

如何用matlab 画散点图 如何标记数据点的颜色

分离散点图并添加线

3D散点图动画

在 Plotly 中将回归平面添加到 3d 散点图

如何将颜色作为第三维添加到 matplotlib 散点图? [复制]