如何避免在具有多个系列的 3D 散点图中对颜色图数据进行归一化
How to avoid normalization of colormap data in 3D scatter plot with multiple series
我正在尝试在 3D 散点图中绘制不同的系列,并使用颜色图在不同系列组合的最小值和最大值之间进行归一化。
问题是每个系列的颜色图值都以不希望的方式单独标准化。也就是说,每个系列的局部最小值和最大值都扩展到颜色图的全局最小值和最大值。
下面的测试代码说明了这个问题(见附图)。颜色图的最小值和最大值为 0 和 100,但系列 1 的范围仅为 0 到 50,与系列 3 的颜色实际上范围为 0 到 100。最后对于只有 1 个值的系列(例如系列 2所有值 = 50) 然后将颜色设置为最小值。
在将数据发送到颜色图(注释掉)之前,我尝试自己进行标准化,因为它只接受 0 到 1 之间的值,但它产生相同的结果。
在此先感谢您的帮助。
'Create test dataframes'
n=11
x1, x2, x3 = np.arange(n), np.arange(n)+10, np.arange(n)+5
y1, y2, y3 = np.arange(n)*2, np.arange(n)*2+10, np.arange(n)*2+5
z1, z2, z3 = np.arange(n)*3, np.arange(n)*3+10, np.arange(n)*3+5
cm1 = np.arange(n)*5
cm2 = np.ones(n)*50
cm3 = np.arange(n)*100
'Create list of inputs'
l_x = [x1, x2, x3]
l_y = [y1, y2, y3]
l_z = [z1, z2, z3]
l_cm = [cm1, cm2, cm3]
l_ax_labels = ['x', 'y', 'z', 'cm']
legend = ['case 1', 'case 2', 'case 3']
'Create figure and axis objects'
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
markers = ['o', 'v', 'x']
'Temperature colormap parameters'
cmap = plt.cm.get_cmap(name='jet')
vmin = 0
vmax = 100
norm = mat.colors.Normalize(vmin=vmin, vmax=vmax)
map = mat.cm.ScalarMappable(norm=norm, cmap=cmap)
font = mat.font_manager.FontProperties(size=14)
'colormap axis properties'
cb = plt.colorbar(map, ax=ax, label=l_ax_labels[3])
cb.ax.yaxis.label.set_font_properties(font)
cb.ax.tick_params(labelsize=14)
'Plot different series'
for i in range(len(l_x)):
'Commented lines perform data normalization before sending, but yield same result'
# l_cm[i] = (l_cm[i] - vmin) / (vmax - vmin)
ax.scatter(l_x[i], l_y[i], l_z[i], marker=markers[i], c=l_cm[i], cmap=cmap)
'Fill in axis titles'
ax.set_xlabel(l_ax_labels[0], fontsize=10)
ax.set_ylabel(l_ax_labels[1], fontsize=10)
ax.set_zlabel(l_ax_labels[2], fontsize=10)
'Legend() requires a dummy plot since function does not support type returned by 3D scatter.'
l_scat_prox = []
for i in range(len(l_x)):
scat_proxy = mat.lines.Line2D([0],[0], linestyle="none", marker=markers[i])
l_scat_prox.append(scat_proxy)
ax.legend(l_scat_prox, legend, numpoints=1)#, loc=2, borderaxespad=-6., fontsize=fontsize_leg)
plt.show()
您想在使用分散时设置 vmin
和 vmax
值。如果将所有三个图的值都设置为 0 和 100,它们将不会自动缩放。来自 docs:
vmin
, vmax
float, default: None
vmin
and vmax
are used in conjunction
with the default norm
to map the color array c
to the colormap cmap
.
If None
, the respective min and max of the color array is used.
如您所见,如果您不设置它们,它将缩放到颜色数组的最小值和最大值,这就是您的绘图中发生的情况。因此,对于您的情况,您可以像这样添加 vmin
和 vmax
:
ax.scatter(l_x[i], l_y[i], l_z[i], marker=markers[i], c=l_cm[i],
cmap=cmap, vmin=0, vmax=100)
我正在尝试在 3D 散点图中绘制不同的系列,并使用颜色图在不同系列组合的最小值和最大值之间进行归一化。 问题是每个系列的颜色图值都以不希望的方式单独标准化。也就是说,每个系列的局部最小值和最大值都扩展到颜色图的全局最小值和最大值。 下面的测试代码说明了这个问题(见附图)。颜色图的最小值和最大值为 0 和 100,但系列 1 的范围仅为 0 到 50,与系列 3 的颜色实际上范围为 0 到 100。最后对于只有 1 个值的系列(例如系列 2所有值 = 50) 然后将颜色设置为最小值。 在将数据发送到颜色图(注释掉)之前,我尝试自己进行标准化,因为它只接受 0 到 1 之间的值,但它产生相同的结果。
在此先感谢您的帮助。
'Create test dataframes'
n=11
x1, x2, x3 = np.arange(n), np.arange(n)+10, np.arange(n)+5
y1, y2, y3 = np.arange(n)*2, np.arange(n)*2+10, np.arange(n)*2+5
z1, z2, z3 = np.arange(n)*3, np.arange(n)*3+10, np.arange(n)*3+5
cm1 = np.arange(n)*5
cm2 = np.ones(n)*50
cm3 = np.arange(n)*100
'Create list of inputs'
l_x = [x1, x2, x3]
l_y = [y1, y2, y3]
l_z = [z1, z2, z3]
l_cm = [cm1, cm2, cm3]
l_ax_labels = ['x', 'y', 'z', 'cm']
legend = ['case 1', 'case 2', 'case 3']
'Create figure and axis objects'
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
markers = ['o', 'v', 'x']
'Temperature colormap parameters'
cmap = plt.cm.get_cmap(name='jet')
vmin = 0
vmax = 100
norm = mat.colors.Normalize(vmin=vmin, vmax=vmax)
map = mat.cm.ScalarMappable(norm=norm, cmap=cmap)
font = mat.font_manager.FontProperties(size=14)
'colormap axis properties'
cb = plt.colorbar(map, ax=ax, label=l_ax_labels[3])
cb.ax.yaxis.label.set_font_properties(font)
cb.ax.tick_params(labelsize=14)
'Plot different series'
for i in range(len(l_x)):
'Commented lines perform data normalization before sending, but yield same result'
# l_cm[i] = (l_cm[i] - vmin) / (vmax - vmin)
ax.scatter(l_x[i], l_y[i], l_z[i], marker=markers[i], c=l_cm[i], cmap=cmap)
'Fill in axis titles'
ax.set_xlabel(l_ax_labels[0], fontsize=10)
ax.set_ylabel(l_ax_labels[1], fontsize=10)
ax.set_zlabel(l_ax_labels[2], fontsize=10)
'Legend() requires a dummy plot since function does not support type returned by 3D scatter.'
l_scat_prox = []
for i in range(len(l_x)):
scat_proxy = mat.lines.Line2D([0],[0], linestyle="none", marker=markers[i])
l_scat_prox.append(scat_proxy)
ax.legend(l_scat_prox, legend, numpoints=1)#, loc=2, borderaxespad=-6., fontsize=fontsize_leg)
plt.show()
您想在使用分散时设置 vmin
和 vmax
值。如果将所有三个图的值都设置为 0 和 100,它们将不会自动缩放。来自 docs:
vmin
,vmax
float, default: None
vmin
andvmax
are used in conjunction with the defaultnorm
to map the color arrayc
to the colormapcmap
. IfNone
, the respective min and max of the color array is used.
如您所见,如果您不设置它们,它将缩放到颜色数组的最小值和最大值,这就是您的绘图中发生的情况。因此,对于您的情况,您可以像这样添加 vmin
和 vmax
:
ax.scatter(l_x[i], l_y[i], l_z[i], marker=markers[i], c=l_cm[i],
cmap=cmap, vmin=0, vmax=100)