2016-01-24 3 views
2

Я пытаюсь добавить вторую ось x в начало графика, используя twiny.Цветная панель Matplotlib перемещает вторую ось x

Если я сделать простой график рассеяния без какого-либо Colorbar, верхняя ось х правильно выровнена с нижней осью х (ММВЙ ниже):

enter image description here

Если добавить Colorbar, хотя, верхняя ось й смещаются:

enter image description here

Как я могу это исправить?


MWE

import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.axes_grid1 import make_axes_locatable 
import matplotlib.gridspec as gridspec 


X = np.array([0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4.]) 
X2 = np.array([122, 85, 63, 50, 23, 12, 7, 5, 2]) 
Y = np.cos(X*20) 
Z = np.sin(X*20) 

fig = plt.figure() 
gs = gridspec.GridSpec(1, 2) 
ax1 = plt.subplot(gs[1]) 
ax2 = ax1.twiny() 

ax1.set_xlim(-0.2, max(X)+0.2) 
plt.tick_params(axis='both', which='major', labelsize=10) 
ax1.minorticks_on() 
ax1.grid(b=True, which='major', color='gray', linestyle='--', lw=0.3) 

SC = ax1.scatter(X, Y, c=Z) 
ax1.set_xlabel("Original x-axis") 

ax2.set_xlim(ax1.get_xlim()) 
ax2.set_xticks(X) 
ax2.set_xticklabels(X2) 
ax2.set_xlabel("Second x-axis") 

# Colorbar. 
the_divider = make_axes_locatable(ax1) 
color_axis = the_divider.append_axes("right", size="2%", pad=0.1) 
cbar = plt.colorbar(SC, cax=color_axis) 
cbar.set_label('B', fontsize=10, labelpad=4, y=0.5) 
cbar.ax.tick_params(labelsize=10) 

plt.show() 
+1

Пожалуйста, сообщите об этом как об ошибке в вверх по течению, двойниковая оси должен отслеживать изменения в другом. – tacaswell

+0

Будет делать @tcaswell, спасибо за подтверждение, что это ошибка. – Gabriel

+1

@tcaswell ошибка здесь: https://github.com/matplotlib/matplotlib/issues/5904 – Gabriel

ответ

4

Вы можете иметь Colorbar 'украсть' пространство от more than one ax

import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.axes_grid1 import make_axes_locatable 
import matplotlib.gridspec as gridspec 

X = np.array([0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4.]) 
X2 = np.array([122, 85, 63, 50, 23, 12, 7, 5, 2]) 
Y = np.cos(X*20) 
Z = np.sin(X*20) 

fig = plt.figure() 
gs = gridspec.GridSpec(1, 2) 
ax1 = plt.subplot(gs[1]) 
ax2 = ax1.twiny() 

ax1.set_xlim(-0.2, max(X)+0.2) 
plt.tick_params(axis='both', which='major', labelsize=10) 
ax1.minorticks_on() 
ax1.grid(b=True, which='major', color='gray', linestyle='--', lw=0.3) 

SC = ax1.scatter(X, Y, c=Z, cmap='viridis') 
ax1.set_xlabel("Original x-axis") 

ax2.set_xlim(ax1.get_xlim()) 
ax2.set_xticks(X) 
ax2.set_xticklabels(X2) 
ax2.set_xlabel("Second x-axis") 

# Colorbar. 
cbar = plt.colorbar(SC, ax=[ax1, ax2]) 
cbar.set_label('B', fontsize=10, labelpad=4, y=0.5) 
cbar.ax.tick_params(labelsize=10) 

plt.show() 

который я думаю, будет не-блокировать ваш случай использования.

Пределы немного разные, потому что я сижу на текущей ветви мастера.

enter image description here

Если вам нужно использовать tight_layout что-то вроде этого (что требует некоторой настройки на прокладках и т.д.):

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.gridspec as gridspec 


X = np.array([0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4.]) 
X2 = np.array([122, 85, 63, 50, 23, 12, 7, 5, 2]) 
Y = np.cos(X*20) 
Z = np.sin(X*20) 

fig = plt.figure() 
gs = gridspec.GridSpec(1, 2) 
right_gs = gridspec.GridSpecFromSubplotSpec(1, 2, width_ratios=[30, 1], subplot_spec=gs[1], wspace=0.05) 

ax1 = fig.add_subplot(right_gs[0]) 
color_axis = fig.add_subplot(right_gs[1]) 



ax2 = ax1.twiny() 

ax1.set_xlim(-0.2, max(X)+0.2) 
plt.tick_params(axis='both', which='major', labelsize=10) 
ax1.minorticks_on() 
ax1.grid(b=True, which='major', color='gray', linestyle='--', lw=0.3) 

SC = ax1.scatter(X, Y, c=Z, cmap='viridis') 
ax1.set_xlabel("Original x-axis") 

ax2.set_xlim(ax1.get_xlim()) 
ax2.set_xticks(X) 
ax2.set_xticklabels(X2) 
ax2.set_xlabel("Second x-axis") 

cbar = fig.colorbar(SC, cax=color_axis) 
cbar.set_label('B', fontsize=10, labelpad=4, y=0.5) 
cbar.ax.tick_params(labelsize=10) 

fig.tight_layout() 
plt.show() 

enter image description here

+0

Если я использую этот код без разделителя, цветные панели отображаются на графиках рассеяния. Если я сделаю цветную панель (используя разделитель) перед тем, как сделать двойной топор (то есть: 'ax2 = ax1.twiny()'), верхняя и нижняя оси x будут смещены. Вы получили это, чтобы работать с некоторой конфигурацией? – Gabriel

+1

См. Редактирование, я добавил изображение того, что получаю для вывода + полный код – tacaswell

+0

Спасибо tcaswell. Я понял, что заставляет цветную панель рисоваться над диаграммами рассеяния: это 'fig.tight_layout()' У меня выше 'plt.show()'. Я не включил эту строку в свой MWE, поэтому ваш вопрос полностью решает исходную проблему. Тем не менее, не знаете ли вы, как я мог бы поддерживать 'fig.tight_layout()' * и * цветные панели, расположенные правильно? – Gabriel

2

Это выглядит как своего рода хак. Но заставляя фигуру рисовать. А затем получить позицию ax1. вы можете установить ax2 на то же самое и перерисовать фигуру.

.... 
cbar.ax.tick_params(labelsize=10) 

fig.canvas.draw() 
ax2.set_position(ax1.get_position()) 

plt.show() 

enter image description here

+0

Это работает, но это заставляет меня сначала рисовать 'fig', что можно сделать на MWE, который я разместил, но не в моем фактическом код. Если ни один другой ответ не сможет обойти эту проблему, я помету ваше, как принято. Спасибо! – Gabriel

Смежные вопросы