我正在尝试制作一个带有两个子图的matplotlib图,每个子图的右侧都有一个色条。这是我的当前代码:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from mpl_toolkits.axes_grid1 import make_axes_locatable
X = tsne_out[:,0]
Y = tsne_out[:,1]
Z = tsne_out[:,2]
fig = plt.figure(figsize = (20,15))
ax1 = fig.add_subplot(221)
ax1.scatter(X, Y, c = material, s = df['Diameter (nm)']/4, cmap = plt.get_cmap('nipy_spectral', 11))
ax1.set_title("2D Representation", fontsize = 18)
ax1.set_xlabel("TSNE1", fontsize = 14)
ax1.set_ylabel("TSNE2", fontsize = 14)
ax1.set_xlim(-20,20)
ax1.set_ylim(-20,20)
ax1.set_xticks(list(range(-20,21,10)))
ax1.set_yticks(list(range(-20,21,10)))
cbar = fig.colorbar(cax, ticks=list(range(0,9)))
cbar.ax.tick_params(labelsize=15)
cbar.ax.set_yticklabels(custom_ticks) # horizontal colorbar
ax2 = fig.add_subplot(222, projection='3d')
ax2.scatter(X, Y, Z, c = material, s = df['Diameter (nm)']/4, cmap = plt.get_cmap('nipy_spectral', 11))
ax2.set_title("3D Representation", fontsize = 18)
ax2.set_xlabel("TSNE1", fontsize = 14)
ax2.set_ylabel("TSNE2", fontsize = 14)
ax2.set_zlabel("TSNE3", fontsize = 14)
ax2.set_xlim(-20,20)
ax2.set_ylim(-20,20)
ax2.set_zlim(-20,20)
ax2.set_xticks(list(range(-20,21,10)))
ax2.set_yticks(list(range(-20,21,10)))
ax2.set_zticks(list(range(-20,21,10)))
cbar = fig.colorbar(cax, ticks = list(range(0,9)))
cbar.ax.tick_params(labelsize=15)
cbar.ax.set_yticklabels(custom_ticks)
这提供了下图:
我的问题是:为什么第一个颜色栏不显示我的自定义刻度,我该如何解决?
答案 0 :(得分:2)
问题似乎是ScalarMappable
个对象似乎最多可以与它们关联一个颜色条。当您使用相同的ScalarMappable
绘制第二个颜色条时,原始颜色条将取消链接,并且第一个颜色条的先前设置将丢失。
您的代码缺少一些细节(特别是cax
的定义),因此您要么必须创建两个单独的mappable,要么直接使用每个scatter
调用给您的内容。此外,我会明确指出您要在何处插入颜色条。
一个示例修复程序,假设cax
确实是指您的散点图:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
X = np.random.rand(100) * 40 - 20
Y = np.random.rand(100) * 40 - 20
Z = np.random.rand(100) * 40 - 20
C = np.random.randint(1,8,100)
custom_ticks = list('ABCDEFGH')
fig = plt.figure(figsize = (20,15))
ax1 = fig.add_subplot(121)
sc1 = ax1.scatter(X, Y, c = C, cmap='viridis') # use this mappable
ax1.set_title("2D Representation", fontsize = 18)
ax1.set_xlabel("TSNE1", fontsize = 14)
ax1.set_ylabel("TSNE2", fontsize = 14)
ax1.set_xlim(-20,20)
ax1.set_ylim(-20,20)
ax1.set_xticks(list(range(-20,21,10)))
ax1.set_yticks(list(range(-20,21,10)))
cbar = fig.colorbar(sc1, ax=ax1, ticks=list(range(0,9))) # be explicit about ax1
cbar.ax.tick_params(labelsize=15)
cbar.ax.set_yticklabels(custom_ticks)
ax2 = fig.add_subplot(122, projection='3d')
sc2 = ax2.scatter(X, Y, Z, c=C, cmap='viridis') # next time use this one
ax2.set_title("3D Representation", fontsize = 18)
ax2.set_xlabel("TSNE1", fontsize = 14)
ax2.set_ylabel("TSNE2", fontsize = 14)
ax2.set_zlabel("TSNE3", fontsize = 14)
ax2.set_xlim(-20,20)
ax2.set_ylim(-20,20)
ax2.set_zlim(-20,20)
ax2.set_xticks(list(range(-20,21,10)))
ax2.set_yticks(list(range(-20,21,10)))
ax2.set_zticks(list(range(-20,21,10)))
cbar = fig.colorbar(sc2, ax=ax2, ticks=list(range(0,9))) # sc1 here is the bug
cbar.ax.tick_params(labelsize=15)
cbar.ax.set_yticklabels(custom_ticks)
plt.show()
这将产生以下结果:
请注意,我为您创建了一个MCVE,并且简化了一些事情,例如子图的数量。关键是,颜色条设置现在使用了独立的可映射对象,因此仍然保持不变。
另一个选择是先创建颜色条(如果需要,可以使用相同的ScalarMappable
),然后再自定义两者:
sc = ax1.scatter(X, Y, c = C, cmap='viridis')
cbar1 = fig.colorbar(sc, ax=ax1, ticks=np.arange(0,9))
ax2.scatter(X, Y, Z, c=C, cmap='viridis')
cbar2 = fig.colorbar(sc, ax=ax2, ticks=np.arange(0,9)) # sc here too
for cbar in cbar1,cbar2:
cbar.ax.tick_params(labelsize=15)
cbar.ax.set_yticklabels(custom_ticks)
以上所述的事实可能表明原始行为是一个错误。