1

Here is a code I have to plot geolocalised data on a Basemap. I would like to add a histogram on the left of my Basemap in order to show the density related to each degree of latitude.

data = np.zeros((5000,3))
data[:,0]=np.random.uniform(low=-180,high=180,size=(5000,))
data[:,1]=np.random.uniform(low=-60,high=90,size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))

fig = plt.figure(facecolor='w')
grid = plt.GridSpec(4, 4, hspace=0.2, wspace=0.2)
main_ax = fig.add_subplot(grid[:-1, 1:])

m = Basemap(projection = 'cyl', llcrnrlat = -60., urcrnrlat = 90., llcrnrlon = -180., urcrnrlon = 180., resolution ='l')
x, y =m(data[:,0], data[:,1])
m.scatter(x, y, marker='.', s = 0.02, c = data_lac[:,2], cmap = 'hot_r', edgecolor = 'none')
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
parallels=np.arange(-60.,90.,10)
m.drawparallels(parallels, labels =[True, False, False, True], linewidth=0.)
m.drawmeridians(np.arange(-180.,180.,20),labels =[True, False, False, True], linewidth=0. )
m.colorbar()

y_hist = fig.add_subplot(grid[:-1, 0], xticklabels=[], sharey=main_ax)

# histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
plt.tight_layout()
plt.show()

I have issues with the size of my histogram that does not fit with the size of the map nor the latitude (if I just want from -60° to 90°). Moreover, the y-axe is not shared between Basemap and the histogram. I also tried with the GridSpec format but the result is the same.

enter image description here

6
  • Have you seen this? Commented Mar 15, 2019 at 16:01
  • Thanks in a sense it's what i'm looking for but in my idea the plot might be dynamic and follow the tick pattern of the main map. I have added an example on my post to show what I'm looking for, i hope it will help! Commented Mar 18, 2019 at 12:21
  • Here is an example where I aligned a basemap plot with a simple line graph. Something similar could be done with a histogram as well. If the example is not enough (e.g. if you need more help), let me know and I can cook up an example for your particular problem. Commented Mar 18, 2019 at 12:33
  • Thanks a lot, I tried your solution. It works well with an histogram and I'm very close to what i'm expecting. Just two last issues, first using subplot seems to attribute the same size to each graph then I can't map my data from -180 to 180. Secondly, I have an issue with the colorbar which seems impossible to autoscale. Commented Mar 19, 2019 at 12:42
  • 1
    It was a message error but using the fig colorbar resolves the issue. Thanks Commented Mar 22, 2019 at 8:55

1 Answer 1

1

Although the answer that I linked in the comments provides a principle solution to the question, a problem may occur, when the aspect ratio of the figure is 'too small'. In this case, even though the yticks and ylims are synchronised, the height of the basemap and the histogram are not, because the aspect ratios of the two subplots are different. The easiest way to fix this is to use an axes divider instead of the usual add_subplot() approach, as it is done in the last example of this answer.

In connection with the my earlier suggested solution to share the yticks between the two plots, one can actually get pretty neat results. For best results, I would recommend to not use basemaps colorbar function, but instead directly use fig.colorbar with a dedicated axes for the color bar. Also, it looks (in my opinion) best if you show the ytick labels only left of the histogram and hide them next to the basemap (solution from here). If this is not wanted, you can adjust the distance between histogram and basemap with the pad keyword in 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()

The final result has truly synchronised subplot heights and yticks (also upon resizing the figure) and looks like this:

result of the above code

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.