Basic Visualization#

At the end of this lesson you will learn:

  1. how to use xarray’s convenient matplotlib-backed plotting interface to visualize your datasets.

  2. that hvplot provides an equally convenient interface for bokeh-backed plots

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr

%config InlineBackend.figure_format='retina'

Load data#

First let’s load up a tutorial dataset to visualize.

ds = xr.tutorial.open_dataset("air_temperature_gradient")
ds
<xarray.Dataset>
Dimensions:  (lat: 25, time: 2920, lon: 53)
Coordinates:
  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0
  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0
  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00
Data variables:
    Tair     (time, lat, lon) float32 ...
    dTdx     (time, lat, lon) float32 ...
    dTdy     (time, lat, lon) float32 ...
Attributes:
    Conventions:  COARDS
    title:        4x daily NMC reanalysis (1948)
    description:  Data is from NMC initialized reanalysis\n(4x/day).  These a...
    platform:     Model
    references:   http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...

This dataset has three “data variables”, Tair is air temperature and dTdx and dTdy are horizontal gradients of this temperature field. All three “data variables” are three-dimensional with dimensions (time, lat, lon).

Basic plotting: .plot()#

DataArray objects have a plot method. This method creates plots using matplotlib so all of your existing matplotlib knowledge carries over!

By default .plot() makes

  1. a line plot for 1-D arrays using plt.plot()

  2. a pcolormesh plot for 2-D arrays using plt.pcolormesh()

  3. a histogram for everything else using plt.hist()

Histograms#

Tair is three-dimensional, so we got a histogram of temperature values. Notice the label on the x-axis. One of xarray’s convenient plotting features is that it uses the attrs of Tair to nicely label axes and colorbars.

ds.Tair.plot()
(array([   2182.,   60537.,  195026.,  233763.,  315219.,  635948.,
         778807., 1192236.,  453381.,    1901.]),
 array([221.        , 230.63999939, 240.27999878, 249.91999817,
        259.55999756, 269.20001221, 278.83999634, 288.47998047,
        298.11999512, 307.76000977, 317.3999939 ]),
 <BarContainer object of 10 artists>)
../_images/2d2a06a9c11903d65b6948e0e79b21bd864b9accdf8f2c2990d5436a302797d3.png

You can pass extra arguments to the underlying hist() call. See the matplotlib docs for all possible keyword arguments.

Tip: Note that the returned values are exactly what matplotlib would return

Exercise#

Update the above plot to show 50 bins with unfilled steps instead of filled bars.

2D plots#

Now we will explore 2D plots. Let’s select a single timestep of Tair to visualize.

ds.Tair.isel(time=1).plot()
<matplotlib.collections.QuadMesh at 0x7fbc6bd3d090>
../_images/0ca0c8e7b183955b8eb593cc9ac804d6629027605efd8a0471ca89dd0135cd4f.png

This is identical to .plot.pcolormesh which is more explicit

ds.Tair.isel(time=1).plot.pcolormesh()
<matplotlib.collections.QuadMesh at 0x7fbc6aaf6390>
../_images/0ca0c8e7b183955b8eb593cc9ac804d6629027605efd8a0471ca89dd0135cd4f.png

Notice how much information is on that plot!

  1. The x- and y-axes are labeled with full names — “Latitude”, “Longitude” — along with units.

  2. The colorbar has a nice label, again with units.

  3. And the title tells us the timestamp of the data presented.

plot.pcolormesh takes many keyword arguments and is quite sophisticated.

Here is a more complicated figure that explicitly sets time as the x-axis, customizes the colorbar, and overlays two contours at specific levels.

Tip: Other options for 2D plots include .plot.contour, .plot.contourf, .plot.imshow

ds.Tair.isel(lon=1).plot(
    x="time",  # coordinate to plot on the x-axis of the plot
    robust=True,  # set colorbar limits to 2nd and 98th percentile of data
    cbar_kwargs={  # passed to plt.colorbar
        "orientation": "horizontal",
        "label": "custom label",
        "pad": 0.3,
    },
)
<matplotlib.collections.QuadMesh at 0x7fbc6ab7d710>
../_images/70672a6127c2e5b8eabffd17747495d8bc48dfbbb9e8005d20318eac54ed4e4e.png

Exercise#

Update the above plot to use a different matplotlib colormap.

Hide code cell source
ds.Tair.isel(lon=1).plot(
    x="time",  # coordinate to plot on the x-axis of the plot
    robust=True,  # set colorbar limits to 2nd and 98th percentile of data
    cmap=mpl.cm.RdYlBu_r,
    cbar_kwargs={  # passed to plt.colorbar
        "orientation": "horizontal",
        "label": "custom label",
        "pad": 0.3,
    },
)
<matplotlib.collections.QuadMesh at 0x7fbc6aa9d1d0>
../_images/06d5bb92956265cd8047867004e0189435e6671d0ddf33885cea8ea9809c81a0.png

Exercise#

Now overlay a contour plot on top of the previous plot

Hide code cell source
ds.Tair.isel(lon=1).plot.pcolormesh(
    x="time",  # coordinate to plot on the x-axis of the plot
    robust=True,  # set colorbar limits to 2nd and 98th percentile of data
    cmap=mpl.cm.RdYlBu_r,
    cbar_kwargs={  # passed to plt.colorbar
        "orientation": "horizontal",
        "label": "custom label",
        "pad": 0.3,
    },
)
ds.Tair.isel(lon=1).plot.contour(
    x="time",  # coordinate to plot on the x-axis of the plot
    levels=5,  # autoselect 5 levels between max, min
    # The following are passed to plt.contour
    colors="k",
    linewidths=0.5,
)
<matplotlib.contour.QuadContourSet at 0x7fbc6a90d010>
../_images/e98fa07a0342dd492c216f71fb8061ce8216edacb584fe7fa5c00d2a931373c3.png

1D line plots#

xarray is also able to plot lines by wrapping plt.plot(). As in the earlier examples, the axes are labelled and keyword arguments can be passed to the underlying matplotlib call.

ds.Tair.isel(time=1, lon=10).plot(marker="o")
[<matplotlib.lines.Line2D at 0x7fbc6bc11d90>]
../_images/90958817a58ed370cc7ee8ae93368d3c6b31602f3031aa6e89c4aeb12c5e6983.png

Again, this is equivalent to the more explicit plot.line

ds.Tair.isel(time=1, lon=10).plot.line(marker="o")
[<matplotlib.lines.Line2D at 0x7fbc6bca99d0>]
../_images/90958817a58ed370cc7ee8ae93368d3c6b31602f3031aa6e89c4aeb12c5e6983.png

Multiple lines with hue#

Lets say we want to compare line plots of temperature at three different latitudes. We can use the hue kwarg to do this.

ds.Tair.isel(time=1).sel(lat=[40, 50, 60], method="nearest").plot(x="lon", hue="lat")
[<matplotlib.lines.Line2D at 0x7fbc6a8a9910>,
 <matplotlib.lines.Line2D at 0x7fbc6a782810>,
 <matplotlib.lines.Line2D at 0x7fbc6a762bd0>]
../_images/0958b9c62bc5a656fb5f6208487c8801fe00e322a866664ab74bee50215501a4.png

Customization#

All of xarray’s plotting functions take an large list kwargs that customize behaviour. A full list can be seen here. That said xarray does not wrap all matplotlib functionality.

The general strategy for making plots that are more complicated that the examples above is

  1. Create a matplotlib axis ax

  2. Use xarray to make a close approximation of the final plot specifying ax=ax.

  3. Use ax methods to fully customize the plot

More resources#

  1. Xarray’s visualization gallery

  2. Xarray’s plotting documentation