Here is the code returning the figure below:
import seaborn as sns
plt.figure(figsize=(8, 8))
gs = plt.GridSpec(3, 3)
ax_main = plt.subplot(gs[1:3, :2])
ax_lon = plt.subplot(gs[0, :2])
ax_lat = plt.subplot(gs[1:3, 2])
m = Basemap(projection='merc', resolution='i', llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat,
urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat, ax=ax_main)
try:
m.drawcoastlines(linewidth=0.5)
except:
pass
m.drawcountries()
m.drawmapboundary()
lon_range = urcrnrlon - llcrnrlon
lat_range = urcrnrlat - llcrnrlat
lat_interval = round(0.2 * lat_range, 2)
lon_interval = round(0.2 * lon_range, 2)
parallels = np.arange(-90, 90, lat_interval)
meridians = np.arange(-180, 180, lon_interval)
m.drawparallels(parallels, labels=[0, 1, 0, 0], fontsize=8, dashes=[1, 5])
m.drawmeridians(meridians, labels=[0, 0, 1, 0], fontsize=8, dashes=[1, 5])
m.fillcontinents(color='#F0F0F0', lake_color='#F0F0F0')
x1, y1 = m(LON_1, LAT_1)
x2, y2 = m(LON_2, LAT_2)
ax_main.scatter(x1, y1, c='steelblue', alpha=.8, s=8, label='Data 1')
ax_main.scatter(x2, y2, c='red', alpha=.8, s=8, label='Data 2')
ax_main.set_xlabel('Longitude', fontsize=12, labelpad=10)
ax_main.set_ylabel('Latitude', fontsize=12, labelpad=10)
ax_main.legend(loc='upper right')
# Histogram of longitude
ax_lon.hist(LON_1, bins=20, histtype='step', density=True, color='steelblue',
align='mid', label='Data 1')
ax_lon.hist(LON_2, bins=20, histtype='step', density=True, color='red',
align='mid', label='Data2')
ax_lon.set_xticks([])
ax_lon.set_yticks([])
#ax_lon.legend(loc='upper right')
# Histogram of latitude
ax_lat.hist(LAT_1, bins=20, histtype='step', density=True, color='steelblue', align='mid',
orientation='horizontal', label='Data 1')
ax_lat.hist(LAT_2, bins=20, histtype='step', density=True, color='red', align='mid',
orientation='horizontal', label='Data 2')
# ax_lat.tick_params(axis='y', rotation=-90)
ax_lat.set_yticks([])
ax_lat.set_xticks([])
#ax_lat.legend(loc='upper right')
plt.tight_layout()
plt.show()
I cannot adjust the histograms' size with sharex/sharey option otherwise they are not properly displayed (do not know why, but I think it has to do with Basemap). Is there a way to adjust the top histogram size such that its x-axis (y-axis) is the same as the x-axis (y-axis) of the map (right histo)?
The top and right (axes) frames need to adopt the related dimensions/positions of the main axes. The commands .get_position()
and .set_position()
are used to operate and get the required plots.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
plt.figure(figsize=(8, 8-2))
gs = plt.GridSpec(3, 3)
ax_main = plt.subplot(gs[1:3, :2]) # lower-left
ax_lon = plt.subplot(gs[0, :2]) # top
ax_lat = plt.subplot(gs[1:3, 2]) # lower-right
llcrnrlon=15.5
llcrnrlat=39.5
urcrnrlon=16.5
urcrnrlat=40
m = Basemap(projection='merc', resolution='i', llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat,
urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat, ax=ax_main)
try:
m.drawcoastlines(linewidth=0.5)
except:
pass
#m.drawcountries()
m.drawmapboundary()
lon_range = urcrnrlon - llcrnrlon
lat_range = urcrnrlat - llcrnrlat
lat_interval = round(0.2 * lat_range, 2)
lon_interval = round(0.2 * lon_range, 2)
parallels = np.arange(-90, 90, lat_interval)
meridians = np.arange(-180, 180, lon_interval)
m.drawparallels(parallels, labels=[1, 0, 0, 0], fontsize=8, dashes=[1, 5])
m.drawmeridians(meridians, labels=[0, 0, 1, 0], fontsize=8, dashes=[1, 5])
m.fillcontinents(color='#F0F0F0', lake_color='#F0F0F0')
# Adjust frames' positions
# get dimensions of the 2 axes
mbox = ax_main.get_position() #_main
box1 = ax_lon.get_position() # top
box2 = ax_lat.get_position() # right, needs both LL & UR
# current dimensions
w0,h0 = mbox.x1-mbox.x0, mbox.y1-mbox.y0
w1,h1 = box1.x1-box1.x0, box1.y1-box1.y0
w2,h2 = box2.x1-box2.x0, box2.y1-box2.y0
# compute/apply new positions for top-frame
new_w1 = w0 # adopt main's w0
new_h1 = h1/w1*w0 # adjust h, retaining w/h ratio
ax_lon.set_position([box1.x0, box1.y0, new_w1, new_h1])
# compute/apply new positions for right frame
new_h2 = h0 # adopt main's h0
new_w2 = w2/h2 * new_h2 # adjust w, retaining w/h ratio
right_LL = [box2.x0, mbox.y0] # align LL horizontally
# finally, apply new position to the right frame
ax_lat.set_position([right_LL[0], right_LL[1], new_w2, new_h2])