0

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()

enter image description here

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)?

1
  • Any comment on my answer?
    – swatchai
    Commented Nov 7 at 13:58

1 Answer 1

0

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])

fig1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.