Хотя ответ, который я привел в комментариях, дает принципиальное решение вопроса, проблема может возникнуть, когда соотношение сторон на рисунке «слишком мало».В этом случае, даже если yticks и ylims синхронизированы, высота базовой карты и гистограммы - нет, потому что пропорции двух подзаговоров различны.Самый простой способ исправить это - использовать разделитель осей вместо обычного подхода add_subplot()
, как это делается в последнем примере этого ответа .
В связи с моимранее предлагало решение , чтобы разделить утики между двумя графиками, на самом деле можно получить довольно аккуратные результаты.Для достижения наилучших результатов я бы рекомендовал не использовать функцию basemaps colorbar
, а вместо этого напрямую использовать fig.colorbar
с выделенными осями для цветовой шкалы.Кроме того, это выглядит (на мой взгляд) лучше всего, если вы показываете метки ytick только слева от гистограммы и скрываете их рядом с базовой картой (решение из здесь ).Если это не нужно, вы можете отрегулировать расстояние между гистограммой и базовой картой с помощью ключевого слова pad
в divider.append_axes()
.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.zeros((5000,3))
data[:,0] = np.random.normal(loc=20, scale = 30, size=(5000,))
data[:,1] = np.random.normal(loc=50, scale=10, size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))
##create a figure with just the main axes:
fig, main_ax = plt.subplots()
m = Basemap(
projection = 'cyl',
llcrnrlat = -60., urcrnrlat = 90.,
llcrnrlon = -180., urcrnrlon = 180.,
resolution ='l',
ax=main_ax,
)
x, y =m(data[:,0], data[:,1])
cls = m.scatter(
x, y,
marker='.', s = 1, c = data[:,2],
cmap = 'hot_r', edgecolor = 'none'
)
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
lats=np.arange(-60.,90.,10)
lons=np.arange(-180.,180.,60)
##parallels without labels
m.drawparallels(lats, labels =[False, False, False, False], linewidth=0.1)
m.drawmeridians(lons,labels =[False, False, False, True], linewidth=0.1 )
##generating the other axes instances:
##if you want labels at the left side of the map,
##adjust pad to make them visible
divider = make_axes_locatable(main_ax)
y_hist = divider.append_axes('left', size='20%', pad='5%', sharey=main_ax)
cax = divider.append_axes('right',size=0.1,pad=0.1)
##use fig.colorbar instead of m.colorbar
fig.colorbar(cls, cax = cax)
## histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
##the y-ticklabels:
_,yticks_data = m(0*lats,lats)
y_hist.set_yticks(yticks_data)
y_hist.set_yticklabels(['{: >3}$^\circ${}'.format(
abs(int(y)), 'N' if y>0 else 'S' if y<0 else ' '
) for y in lats])
##turning off yticks at basemap
main_ax.yaxis.set_ticks_position('none')
plt.setp(main_ax.get_yticklabels(), visible=False)
plt.tight_layout()
plt.show()
Конечный результат имеет истинно синхронизированные высоты и утилики подпрограмм (также при изменении размерарисунок) и выглядит так:
![result of the above code](https://i.stack.imgur.com/0i9nO.png)