Search code examples
matplotlibpython-xarraycartopyfacet-grid

Why does subplot_kws projection hides the lat and lon?


With a xarray dataset, how can I use FacetGrid with a specific cartopy projection and keep the latitude and longitude values along the axis?

I was trying to use faceting as described in the user-guide here. As soon as I try to give the subplots a specific projection, I lose the lat and lon values on the axis

here is an example:

import xarray as xr
import cartopy.crs as ccrs

airtemps = xr.tutorial.open_dataset("air_temperature")
air = airtemps.air - 273.15
t = air.isel(time=slice(0, 365 * 4, 250) )
g_simple = t.plot.contourf(x="lon", y="lat", col="time", col_wrap=3,
                           transform = ccrs.PlateCarree(),
                           subplot_kws={"projection": ccrs.PlateCarree()},
                           levels=51,
)

enter image description here

but if I comment out the projection line

import xarray as xr
import cartopy.crs as ccrs

airtemps = xr.tutorial.open_dataset("air_temperature")
air = airtemps.air - 273.15
t = air.isel(time=slice(0, 365 * 4, 250) )
g_simple = t.plot.contourf(x="lon", y="lat", col="time", col_wrap=3,
                           #  subplot_kws={"projection": ccrs.PlateCarree()},
                           levels=51,
)

enter image description here

Why does it happen? and how can i fix this?


Solution

  • Cartopy turns the axis labels off by default because they do not make sense for all of Cartopy's projections. You can turn them on again by using the set_visible method on each axis. I also here added coastlines because I think it helps make it obvious where we are looking.

    It seems that xarray is using tight_layout underneath somewhere. I couldn't figure out how to make space for the labels and keep the colorbar in the right place with tight_layout so I switched to using the more modern compressed layout. It turns out you can't switch the layout engine in this way if you already have a colorbar, so I turned the colorbar off initially in the call to contour and added back after switching layout engines.

    import xarray as xr
    import cartopy.crs as ccrs
    import matplotlib.pyplot as plt
    
    airtemps = xr.tutorial.open_dataset("air_temperature")
    air = airtemps.air - 273.15
    t = air.isel(time=slice(0, 365 * 4, 250) )
    g_simple = t.plot.contourf(x="lon", y="lat", col="time", col_wrap=3,
                               transform = ccrs.PlateCarree(),
                               subplot_kws={"projection": ccrs.PlateCarree()},
                               levels=51, add_colorbar=False
    )
    
    for ax in g_simple.axs.flat:  # loop through the map axes
        subplotspec = ax.get_subplotspec()
        if subplotspec.is_last_row():
            ax.xaxis.set_visible(True)
        if subplotspec.is_first_col():
            ax.yaxis.set_visible(True)
        ax.coastlines()
        
    g_simple.fig.set_layout_engine("compressed")
    g_simple.fig.get_layout_engine().set(h_pad=0.2)  # More vertical space between maps
    g_simple.add_colorbar()
    
    plt.show()
    
    

    [image upload seems to be currently broken across StackOverflow]