Две цветные полосы на двух участках, одна и та же фигура

1

Я пытаюсь сделать график 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)

Это дает следующий рисунок: Изображение 174551

Мой вопрос: почему первая панель цвета не показывает мои пользовательские тики и как я могу это исправить?

Теги:
matplotlib
plot
data-visualization
colorbar

1 ответ

1
Лучший ответ

Кажется, проблема заключается в том, что объекты ScalarMappable похоже, могут иметь не более одного связанного с ними цветного экрана. Когда вы рисуете второй цветной план с тем же ScalarMappable, исходная панель цветов отсоединяется, а предыдущие настройки теряются для первой панели цветов.

Ваш код не хватает некоторых деталей (в частности, определение cax), так что вы должны либо создать два отдельных mappables, или непосредственно использовать то, что каждый 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()

Это дает следующее:

Изображение 174551

Обратите внимание, что я создал 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)

Тот факт, что вышеупомянутые работы могут предполагать, что исходное поведение является ошибкой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню