UPDATE: I now get the subplots in the right positions and with the right data displayed! There is, however, a problem left, and that is that I can't give the subplots their own title and colorbar. Actually, I'd rather have just one colorbar to the right of all the plots, but that doesn't seem to work either. Here is my new code along with some sample data (with is extremely uninsightful, but just for testing purposes):
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import cartopy.crs as ccrs
lons = np.arange(-180,180,1)
lats = np.arange(-80,80,1)
dens = np.zeros((12, len(lons), len(lats)))
for i in range(12):
dens[i,:,:] = i
def plotTitle(yr):
letter = chr(yr-2002+97)
return '(' + letter + ') ' + str(yr)
def DensityPlot(yr, lon, lat, dens, ax):
Lat, Lon = np.meshgrid(lat, lon)
density = ax.pcolormesh(Lon, Lat, dens, cmap = 'jet')
#cbar = ax.colorbar(density, orientation='vertical', shrink=0.5, extend='both') # this gives an error: ''GeoAxesSubplot' object has no attribute 'colorbar''
ax.coastlines()
plt.title(plotTitle(yr),fontsize=14,fontweight='bold') # this only works for the last plot. ax.title doesn't work, gives the error ''Text' object is not callable'
fig, axes = plt.subplots(nrows=6, ncols=2, figsize=(35,35), subplot_kw={'projection': ccrs.PlateCarree()}) ## check figsize
i=0
for ax in axes.flat:
densdata = dens[i,:,:]
density = DensityPlot(i+2002, lons, lats, densdata, ax)
i=i+1
#ax.title(plotTitle(i+2002)) # this gives the same error as mentioned before: ''Text' object is not callable'
#cbar = plt.colorbar(density, orientation='vertical', shrink=0.5, extend='both')
# this gives the following RuntimeError: No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf).
fig.subplots_adjust(right=0.5)
How can I make sure every subplot has its own title, and there is a colorbar next to all the subplots?
I have a problem creating a set of subplots in Python. I have defined a function that produces a specific plot:
def DensityPlot(lon, lat, dens):
Lat, Lon = np.meshgrid(lat, lon)
fig = plt.figure(figsize=(12,12))
ax = plt.axes(projection=ccrs.PlateCarree())
density = plt.pcolormesh(Lon, Lat, dens, cmap = 'jet')
cbar = plt.colorbar(orientation='vertical', shrink=0.5, extend='both')
cbar.set_label("Plastic Density ($10^{-3}$ particles km$^{-2}$)", rotation=90,fontsize=12)
ax.coastlines()
return density
Now I want to use this function in a for-loop to produce subplots. For simplicity, let's assume I can use the same values for lat
, lon
and dens
in every subplot (so I would just get the same plot multiple times). Then, however, the following code does not work:
fig, axes = plt.subplots(nrows=6, ncols=2)
for j in range(0,12):
plt.subplot(6,2,j+1)
density = DensityPlot(lon, lat, dens)
The following thing happens: first, 12 empty plots are displayed, although they are in the correct order (6x2). After that, 11 empty plots appear underneath each other, and finally the very last plot is actually shown the way it should be displayed. I have checked the code for the function DensityPlot
to just create single plots and know that it works fine for that, so the problem must be in the subplot creation. What could be the problem here, and how do I solve it?
You suspect it yourself, you are creating your subplots outside of the loop, but then creating a new figure each time your function is called.
You should create your figure and axes first with the required projection:
fig, axes = plt.subplots(nrows=6, ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})
You can then loop through your axes, and pass it as an argument to your function (making sure to remove any figure or axes creation in the figure itself):
def DensityPlot(lon, lat, dens, ax):
Lat, Lon = np.meshgrid(lat, lon)
density = ax.pcolormesh(Lon, Lat, dens, cmap = 'jet')
cbar = ax.colorbar(orientation='vertical', shrink=0.5, extend='both')
cbar.set_label("Plastic Density ($10^{-3}$ particles km$^{-2}$)", rotation=90,fontsize=12)
ax.coastlines()
return density
for ax in axes.flat:
density = DensityPlot(lon, lat, dens, ax)
In order to add a title to each subplot you need to use ax.set_title()
in your function:
ax.set_title(plotTitle(yr))
There are many other questions on adding a colorbar for multiple subplots. For example Matplotlib 2 Subplots, 1 Colorbar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With