As soon as the temperature rises a little, the question comes up: sure, it's hot, but is it abnormally hot? Is it the usual heat for a summer month, or is it abnormal?
If you want to learn how to answer this question, this tutorial is for you!
Let's take a look:
What a standard climatological normal is, as defined by the World Meteorological Organization,
How to calculate a local normal despite the limited availability of meteorological observations thanks to reanalyses,
How to access these data worldwide via the “Climate data store” of the European Earth Observation Program,
How to calculate annual and monthly temperature normals with Python.
What is a climate normal?
It's not easy to define a normal temperature, especially when, as now, the climate is not stationary. In this tutorial, however, we'll stick to the definition given by the World Meteorological Organization:
A normal is an "average calculated for a uniform and relatively long period comprising at least three consecutive ten-year periods".
So there is not just one normal, but many. The WMO distinguishes between :
Standard normals covering a 30-year period beginning on January 1 of a year ending in 1. For example, the most recent standard normal according to the WMO definition is now 1991-2020.
Among standard normals, the reference normal calculated between January 1, 1961 and December 31, 1990.
Additional note: results are expressed to the nearest tenth. According to the WMO, it is generally not useful to publish normals with greater precision.
No weather observations? (Almost) no problem!
In this tutorial, we're going to calculate the standard normal from 01/01/1981 to 31/12/2010, for the temperature in the good city of Tarbes (Hautes-Pyrénées).
The first difficulty immediately arises, and not the least: where can we find a local temperature history going back more than 40 years?
In reality, reliable temperature measurements over such a long period are extremely rare. In mainland France, the Global Historical Climatology Network refers to less than thirty stations, and unsurprisingly there are none in Tarbes: the nearest are at the Pic du Midi observatory and at Toulouse-Blagnac airport...
Very often, there are no local weather observations over a long enough period to calculate a normal. In this case, the solution is to use a reanalyzed history.
Reanalysis is a method that combines observations (stations, satellite, radar, etc.) and a meteorological model to produce a history with fine spatial and temporal resolution.
The production of reanalyses is within the reach of only a few major forecasting centers, the best known of which are the National Center for Environmental Prediction (NCEP) in the USA and the European Center for Medium-Range Weather Forcasts (ECMWF) in Europe. We will be using data from the latter.
Manual access to ERA5-Land temperature reanalysis
To access ECMWF reanalysis data, including ERA5-Land, the most immediate solution is to go to the Climate Data Store of Copernicus, the European Earth observation program.
If you haven't already done so, create an account on the CDS.
Several reanalyses are available, the most recent and most detailed being ERA5-Land. You can find it by typing “ERA5 Land” in the search field:
Two time steps are available: monthly and hourly. We will (much to the chagrin of our internet provider) use hourly data, which you can select by clicking on “ERA5-Land hourly data from 1981 to present” in the search results.
The “Download data” tab allows you to select the data you wish to download:
In the “Variable” field, tick the temperature at 2 meters above ground: “2m temperature” (and note the impressive number of variables available!),
In the “Year” field, select a year, e.g. 1981,
In the “Month” fields, select a month.
In the “Day” and “Time” fields, click on “Select all” each time,
To avoid overloading our hard disk, we won't be downloading data for the whole planet, but only for mainland France. In the “Geographical area” field, select “Sub-region extraction” and fill in the area limits: 41 for south latitude, 52 for north latitude, -5 for west longitude and 9 for east longitude. You could of course choose another zone, but beware of the volume of data: 30 years of hourly reanalysis for France already represents almost 8GB.
Finally, in the “Format” field, select “NetCDF”.
If you are logged in, you can now click on “Submit form”. You'll then have to wait for the file to be ready (which may take a little while), download it and repeat as many times as necessary...
Needless to say, you'll quickly tire of this method: as the Climate Data Store only allows manual downloading of one month at a time, you'll need to make 360 downloads to get the 30 years of data you need!
Automated downloading with the Climate Data Store API and Python
If you want to save yourself this tedious work, there's a more efficient solution: use the Climate Data Store API.
Please note: due to a change in Copernicus services in 2024, old accounts and tokens are no longer valid. To access ERA5-Land, you will need to create an ECMWF account and update the .cdsapirc file, even if you have already downloaded reanalyses from the Climate Data Store.
To begin, install the cdsapi library, for example with :
pip install cdsapi
Create an account or log in to the Climate Data Store and go to your profile. There you will find your ID and a token to access the data:
Look for a file on your hard disk called .cdsapirc, normally located in “C:\Users\Username”. Open this file with a text editor and copy your :
Once this is done, save the .cdsapirc file and close.
We can now download the data directly with a few lines of Python :
If you haven't already done so, an error message will ask you to accept ERA5-Land's terms of use. Go to the link provided and check the box.
Running the above code will download the reanalyzed temperature between 1981 and 2010 in the form of annual files called, for example, ERA5Land_t2m_France_2010.nc. All you need now is patience...
Calculation of the 1981-2010 annual normal
Once the temperature histories have been downloaded, let's move on to processing.
The files are opened with xarray :
import xarray as xr
import os
dossier = "ERA5Land_Temperature"
DS = xr.open_mfdataset(os.path.join(dossier, '*.nc'))
open_mfdataset() automatically opens and combines all .nc files in the “ERA5Land_Temperature” folder into a single dataset, DS.
A dataset can contain several datasets (or DataArray) sharing a coordinate system, e.g. temperature and precipitation on the same geographic grid, over the same period and with the same time step. This is not the case here, since we only have temperature, but we still need to extract the unique DataArray from our dataset.
The syntax is the same as for accessing a dictionary value, using the variable name as the key: DS['t2m']. Or more simply :
da = DS.t2m
You can see which unit is used with :
da.attrs[‘units’]
The temperature is in Kelvin. Celcius degrees would be more appropriate, so we will convert :
da = da - 273.15
da.attrs['units'] = '°C'
Let's now select the temperatures in Tarbes. A quick search reveals that the town is located at latitude 43.2333 and longitude 0.0833.
We can round these values to the nearest tenth, which corresponds to the spatial resolution of ERA5-Land, or simply use method = 'nearest', which will return the nearest data point:
lat = 43.2333
lon = 0.0833
da_Tarbes = da.sel(latitude = lat,
longitude = lon,
method = 'nearest',
drop = True)
drop = True deletes unnecessary latitude and longitude coordinates. By default, these coordinates would be kept with a single value: 43.2 for latitude and 0.1 for longitude.
The result is a DataArray containing the temperature in degrees Celcius in Tarbes for each hour between 1981 and 2010.
Let's put all this into a function, which will certainly simplify our lives later on:
We return to our Tarbes temperature series with :
lat = 43.2333
lon = 0.0833
da_Tarbes = temperature_horaire(lat, lon)
To obtain the annual normal, we simply take the average of this DataArray :
da_Tarbes.mean()
The result is still in the form of a DataArray, which requires a few detours to obtain a float which, in accordance with WMO recommendations, we will round to the tenth:
da_Tarbes_normale = da_Tarbes.mean()
normale = round(float(da_Tarbes_normale.values), 1)
Finally, we obtain the 1981-2010 normal for annual temperature: 11.6°C.
Calculating monthly normals
An annual average is all very well, but it doesn't really help to know whether the temperature on July 21, 2020 is normal or not... For that, a monthly normal would be more useful.
Nothing too complicated. Let's take our hourly DataArray:
lat = 43.2333
lon = 0.0833
dossier = "ERA5Land_Temperature"
da_Tarbes = temperature_horaire(lat, lon, dossier)
We don't really need hourly temperatures. So let's start by resampling with a daily time step:
da_Tarbes_j = da_Tarbes.resample(time = '1D').mean()
Then simply group by month and take the average:
da_Tarbes_normales_m = da_Tarbes_j.groupby(‘time.month’).mean()
You can access the values as before with .values and see that the normal for July is 19.0°C, but these results will be easier to understand on a graph:
And there you have it:
It's simple, right?
Let's take it a step further...
It is possible to take the analysis a step further with, for example, a quantile study or a “moustache box” graph:
The code for this graph is as follows:
This graph shows that the median daily average temperature in July in Tarbes was 18.9°C, with a third quartile at 21.1°C and a maximum at 27.3°C. In other words, half of all July days between 1981 and 2010 had an average temperature above 18.9°C, a quarter above 21.1°C and none above 27.3°C (on average, it may have been hotter during the day).
We are now well equipped to know whether the day's temperature is exceptional or not.
Conclusion
Before concluding, a few remarks. One of the advantages of this calculation is that a normal has a certain predictive value: if you carry out a heat-sensitive activity in Tarbes, you now have a good basis for constructing realistic temperature assumptions.
According to the WMO guide quoted above: normals "are used to implicitly determine the conditions that can most likely be expected in the near future at a given location".
There are two limitations: firstly, just because a meteorological phenomenon hasn't occurred in 30 years doesn't mean it won't happen tomorrow: a day at 28°C or 29°C in July in Tarbes is certainly unlikely, but that doesn't mean it's impossible, even in a stationary climate. If the stakes are high, further statistical analysis (using extreme value theory, for example) is essential.
The climate has already changed. Want to check? Try our "Ca chauffe" application to see how the temperature in your place has changed since 1950.
The climate has already changed. Want to check? Try our “Ca chauffe” application to see how the temperature in your home has changed since 1950.
Secondly, the climate is changing rapidly as a result of our greenhouse gas emissions. A 1981-2010 normal does not necessarily reflect the climate of 2020, and certainly not that of 2050. For projects with a long lifespan - real estate or infrastructure projects, for example - climate assumptions should not be based on past averages. In these contexts, climate projections are useful for providing a picture of future climate, or at least for assessing uncertainties.
This is a subject we have already covered in a previous tutorial, and on which we offer a number of case studies.
As you will have gathered, in many fields, the study of climatic normals is a prerequisite for ensuring the safety and profitability of a project. With climate change, these assessments are becoming more complex.
Do you need up-to-date, reliable information? We can help. Callendar is a French start-up specializing in the provision of climate data. Contact us now: we offer simple solutions tailored to the needs of companies, local authorities and individuals.