1

I'm using matplotlib's basemap functionality to plot data points on a map. Each point is weighed by how many co-occurring points exist within a 5-kM radius. I'd like to put a reference table that corresponds to different-sized outbreaks at the bottom, however I can't figure out how to do this. This is my code so far:

map = Basemap(llcrnrlon=-20.,llcrnrlat=-40,urcrnrlon=160.,urcrnrlat=40.,projection='cyl', lat_0=13.5317, lon_0=2.4604)
map.drawmapboundary(fill_color='paleturquoise')
map.fillcontinents(color='olivedrab',lake_color='paleturquoise')
map.drawcoastlines()
map.drawcountries()
map.drawstates()
used = set()
for i,j,k,n in DATA:
    if map.is_land(i,j):
        if k in used: continue
        used.add(k)
        alpha = 0.5
        if n == 1:
            alpha = 1

        n *= 3
        map.plot(i, j, marker='o',color='r',ms=n, alpha=alpha)

plt.show()

note, DATA is a list of 4-tuples. Each entry in the 4-tuple corresponds to the (latitude, longitude, unique ID corresponding to points co-occuring within a 5x5 km square, number of points with the same uniq ID)

result:

enter image description here

lstbl
  • 527
  • 5
  • 17

1 Answers1

2

The most obvious option is to first create custom labels and handles in matplotlib and then to intitialize a custom legend with them. For instance, if we choose a "showcase" sample of five point sizes, ranging from 1 to 5, you might want to do something along the lines of:

def outbreak_artist(size):
    """ Returns a single-point marker artist of a given size """
    # note that x3 factor corresponds to your
    # internal scaling within the for loop
    return plt.Line2D((0,), (0,), color='r', marker='o',
                      ms=size*3, alpha=alpha, linestyle='')

sizes = [1, 2, 3, 4, 5]

# adapted from https://stackoverflow.com/a/4701285/4118756
# to place the legend beneath the figure neatly
ax = plt.gca()
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])

red_dots = [outbreak_artist(size) for size in sizes]
labels = ["{} outbreaks".format(size) for size in sizes]

ax.legend(red_dots, labels, loc='upper center',
          bbox_to_anchor=(0.5, -0.05), ncol=5)

plt.show()

umbrella_corps_ltd

I fiddled with the legend positioning a bit to bring it out of the plot following this post.

P.S.: I think I ran fig, ax = plt.subplots(figsize = (9.44, 4.76)) before making a Basemap to make the legend size align with the map size.

Community
  • 1
  • 1
Vlas Sokolov
  • 3,733
  • 3
  • 26
  • 43