I'm looking to make a basemap with a scatterplot on top with the zorder of the points determined by the size of each individual point, so that no point ends up totally covered by another. (The ideal end result would look like a bullseye.)
Let's say I have the following code:
Ca_data = array([0.088, 0.094, 0.097, 0.126, 0.112, 0.092, 0.076, 0.105])
SO4_data = array([0.109, 0.001, 0.001, 0.007, 0.214, 0.005, 0.008, 0.559])
longitude = linspace(-101, -100, 8)
latitude = linspace(34.5, 35, 8)
m=Basemap(llcrnrlon=-101,llcrnrlat=34.5,urcrnrlon=-100,urcrnrlat=35,resolution='c', epsg=4326)
m.arcgisimage(server='http://server.arcgisonline.com/ArcGIS', service='ESRI_Imagery_World_2D', xpixels=1500, ypixels=1500, zorder=1)
m.scatter(longitude, latitude, latlon=True, s=6000*Ca_data,c='r',marker="o",label='Ca')
m.scatter(longitude, latitude, latlon=True, s=6000*SO4_data,c='b',marker="o",label='SO4')
plt.show()
As it is, anywhere SO4 is larger than Ca, I would only see SO4. I've considered going in and adding a zorder to each line, but I don't think that would work well since I have several more elements to add in with the same issues. Any ideas?
The only way I can see how to do this is to plot both your datasets at once. Otherwise there's no way to not plot the second dataset on top of the first.
Most of this can be done easily, the only issue is the label
kwarg of scatter
. We can give elementwise (array_like
) sizes and colours for scatter
, but we can't do that with labels. Still, as the visualization of the data is much more important, I'd go down this route, hacking up label-related issues (a legend, mostly) later:
import numpy as np
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
Ca_data = np.array([0.088, 0.094, 0.097, 0.126, 0.112, 0.092, 0.076, 0.105])
SO4_data = np.array([0.109, 0.001, 0.001, 0.007, 0.214, 0.005, 0.008, 0.559])
longitude = np.linspace(-101, -100, 8)
latitude = np.linspace(34.5, 35, 8)
# this is the new part: concatenate all the data
plotlon = np.tile(longitude,2)
plotlat = np.tile(latitude,2)
plotdat = np.concatenate((6000*Ca_data,6000*SO4_data)) # sizes
cdat = np.repeat(('r','b'),longitude.size) # colors
# determine reverse sorting order
inds = np.argsort(plotdat)[::-1]
plt.figure()
m = Basemap(llcrnrlon=-101,llcrnrlat=34.5,urcrnrlon=-100,urcrnrlat=35,resolution='c', epsg=4326)
m.arcgisimage(server='http://server.arcgisonline.com/ArcGIS', service='ESRI_Imagery_World_2D', xpixels=1500, ypixels=1500, zorder=1)
# use a single scatter() call, with ordered-concatenated data
m.scatter(plotlon[inds], plotlat[inds], latlon=True, s=plotdat[inds],c=cdat[inds],marker="o") # label has been removed!
plt.show()
Generalization to n
datasets is straightforward: you need to tile
your latitudes and longitudes n
times instead of 2, and you need a colour for each dataset that you then repeat
.