Visualise Climate Data Using Cartopy and Xarray — Climate Data Visualisation With Python

Lubomir Franko
7 min readJun 28, 2022

--

Image by Author

Although there are many BI tools nowadays, Python is still an excellent tool to visualise data. Its simplicity allows users to read plenty types of data quickly and in a meaningful way.

It is very efficient in reading unstructured data, for example the data about our climate. Most of this data is commonly distributed either in grib/grib2 format (which is widely used in meteorology) or as NC files (NetCDF’s format used for storing multidimensional data).

Since climate change has been urging many large companies and governments to gather data about our changing planet, there are now petabytes of data that can be downloaded for free and used for good purpose and general knowledge.

You can create meaningful charts in just a couple of lines of codes and in a small fraction of time. Using libraries like xarray and cartopy, we can quickly select the data that we want, clip the data, transform the data, plot the data over map in specific coordinate system and much more.

Reading Data With xarray

I have tried many libraries to explore climate data as GDAL, rasterio, pygrib, cfgrib and many more. To be honest, I encountered many issues and limitations working with the above mentioned libraries. It was either too complicated to install or contained cross-dependencies that caused unexpected errors. I am not saying that they are not good. Some people are using these libraries and they may be suitable for specific users. However, for climate and meteorological data, I found xarray as most suitable and versatile library. It is also important to mention that cfgrib library is used as backend engine to read grib files in xarray.

Let’s go to short introduction of xarray. We will first explore the dataset and then create simple plots using xarray and its plot methods.

Explore Dataset

For this analysis, we will use grib files that we already explored in my first article. It will be stored under data/1month_anomaly_Global_ea_2t_201907_1991–2020_v02.grib

This dataset contains temperature anomalies across the globe, averaged over monthly period of July 2019. This anomaly is computed as deviation of temperature from long-term average of years 1991 to 2020.

Structure of xarray’s Dataset class returned from code above (Image by Author)

After we open our grib file, we can see Dimensions, Coordinates, Data variables and Attributes. Each of these elements contain useful information about our data. As we can see, we have two dimensions — latitude and longitude. These dimensions are also coordinates for our data — meaning that every single point in our data must have unique combination of latitude and longitude. Coordinates time, step, heightAboveGround and valid_time have only one value — it is single information that is valid for all the elements in our underlying DataArray.

The most important data for us is stored in Data variables, in this case with key t2m. This is our underlying DataArray that carries all the information about temperature. This DataArray must have exactly the shape of MxN (in our case M being longitude and N being latitude) — every element of t2m DataArray contains unique combination of latitude and longitude.

Create Simple Plots

To visualise DataArray, we can simple type data[“t2m”].plot(). Note that the data is stored in Kelvins. However, since this dataset contains anomalies, it does not matter if we store it as Kelvins or as Degrees Celsius — 1 degree Celsius above average is exactly the same as 1 Kelvin above average.

data["t2m"].plot()

As we can see, this is very simple plot of our dataset. Although we can see the temperature anomalies correctly plotted over longitude and latitude axes, it lacks more context. Using cartopy, we can add gridlines, coastlines, borders, rivers and so on. Moreover, we can change our coordinate reference system to transform the data according to our needs.

Creating Map With Cartopy

Using cartopy, we can easily switch between different Coordinate Reference Systems, changing projection of our map. We can add gridlines, coastlines, borders of countries, rivers, roads and many more. First of all, it is important to know the difference between Coordinate Reference Syestem (CRS = Geografic Coordinate System — GCS) and Projected Reference System (PRS). In our code, we will use projection to talk about PRS and crs to talk about CRS.

Our data is stored with latitude and longitude in degrees. It can be stored in different units as well (eg. distance in meters from specific point on map in x and y direction) but this isn’t our case. Since crs of our data is specified in degrees, we will use cartopy’s CRS called PlateCarree. This is how we ensure that we plot the data at desired locations.

Long story short, we will use projection to specify projection of our map and crs to tell our code where on the map should the data be plotted. Let’s jump back into the code.

Create Basemap

This generates our basemap with Mercator projection, gridlines indicating degrees latitude and longitude, borders and coastlines while having our extent set to Europe. You can specify any extent you want.

Plot the Data Over Basemap

Now let’s plot the data over our basemap. One would think that it will require some extra data manipulation, but that’s not true. To plot the data over our basemap, we simply add 1 line of code. I will add couple more lines to plot colorbar as I like it. Our code for this map will look like this:

Image by Author

Note that it can take considerable amount of time to plot (mine took 49s). It is because we are plotting whole dataset, no matter the extent we specified. Extent is applied after we plot the data. This can be proven also by the colorscale that was automatically chosen. It has range far beyond of what can we see on the map.

Slice the data

To speed up the process, best practice is to slice the data to our specific extent. It will ensure that we are plotting only the data within our extent. This can be simply done with xarray’s sel and slice:

Doing this, we went from 49s to 5s. That makes a HUGE difference!

Fix White Line

If you look at the map carefully you can spot the issue — white line on 0 degrees longitude. This is caused by the way we store our longitudes. In this dataset, we use 0 to 360 degrees convention. This means that our dataset starts at 0 degrees longitude and ends at 360 degrees longitude. We have 2 options how to change this:

  • add cyclic point to wrap our dataset around,
  • convert longitudes to -180 to 180 convention (note that this will create white line on the opposite side of Earth — on 180 degrees longitude, but it won’t be visible on our map since it is not within our specified extent).

Best option would be to use both of them. For simplicity of this article, we used the second option which does not require too much coding and deep understanding of cyclic points.

Note that we firstly create dummy dimension called _longitude_adjusted. We use xr.where() method — we subtract 360 from every longitude greater than 180. Then we swap longitude with _longitude_adjusted and drop longitude. In the end, we rename _longitude_adjusted back to longitude.

Wrap Up

To wrap up, here is our final code, to slice the data and to remove white line out of our plot.

Image by Author

Conclusion

This article showed us how easy it is to use xarray with combination of cartopy. Using these two libraries, data analysts can visualise Climate Data more quickly and efficiently. There is so much free data to explore, especially on Climate Data Store.

In the upcoming article, we will talk about how to create custom map extent while ensuring that it has always 16:9 aspect ratio.

If you liked this article, don’t hesitate to follow my account. Any comments are welcomed and I’d be glad to answer any of your questions. Thank you for your attention and I look forward to explore more data with you.

The notebook from this article can be found on my GitHub page.

Stay Connected

--

--

Lubomir Franko

Experienced Data Engineer writing about Python, Spark and Geospatial Analysis