# Calculating annual mean temperature from ERA5 data in Earth Engine

I am calculating bioclimatic variables using temperature data from ERA5 in Google Earth Engine. ERA5 has 488 images, one for mean monthly temperature for all months 1979-2019.

For calculating annual mean temperature (BIO1), do I take the mean across all 488 images as simple as:

``````var era5_meantemp = era5_complete.select(['mean_2m_air_temperature']);
var era5_meantemp_annual= era5_meantemp.mean(); //unit= kelvin
``````

...or am I supposed to take the mean of the temp of all months in a year i.e., one annual mean temp for 1979, for 1980.... and have an image collection of annual mean temperature for all years i.e. 40 images (2019-1979)? If yes, how do I further calculate one value across all 40 years?

• user:2856 help? Jan 16, 2020 at 10:07

Applying `.mean()` to the collection will return a single image that represents the mean of all monthly means; essentially mean temperature 1979 to 2019.

To calculate a collection of mean annual temperature images (one image per year), you can use the code below. It:

1. Reduces the image collection to a set of distinct year representatives.
2. Performs a join between the distinct year collection and the complete collection to group images by year.
3. Maps a function over the distinct year collection to calculate mean annual temperature from the list of images belonging to each year in the time series.

Note that I also included code to a make a time series chart for a region or interest.

Code Editor script

``````// Import image collection.
var era5_complete = ee.ImageCollection("ECMWF/ERA5/MONTHLY");

// #############################################################################
// ### Make mean annual temperature image collection ###
// #############################################################################

// Reduce the collection to a set of unique year representatives
// to serve as the primary collection in a join with the complete
// collection.
var distinctYear = ee.ImageCollection("ECMWF/ERA5/MONTHLY").distinct('year');

// Define a filter that identifies which images from the complete collection
// match the 'year' from the distinctYear collection.
var filter = ee.Filter.equals({leftField: 'year', rightField: 'year'});

// Define a join.
var join = ee.Join.saveAll('sameYear');

// Apply the join and convert the resulting FeatureCollection to an
// ImageCollection.
var joinCol = ee.ImageCollection(
join.apply(distinctYear, era5_complete, filter)
);

// Apply mean reduction among same year collections.
var annualMonthlyMeanCol = joinCol.map(function(img) {
var yearCol = ee.ImageCollection.fromImages(
img.get('sameYear')
);
return yearCol.mean()
.set('Year', img.get('year'));
});

// #############################################################################
// ### Regional mean annual temperature time series chart ###
// #############################################################################

// Define an area of interest to calculate regional mean annual temperature for.
var aoi = ee.Geometry.Polygon(
[[[-122.14909071938769, 37.21291770869186],
[-122.14909071938769, 37.01360552399172],
[-121.82224745766894, 37.01360552399172],
[-121.82224745766894, 37.21291770869186]]], null, false);

// Display AOI on map.
Map.centerObject(aoi, 10);

// Map over the mean annual temperature collection - for each image calculate
// regional mean and return a feature. Result is a collection that can be
// plotted with ui.Chart.feature charts.
var regionalTemp = annualMonthlyMeanCol.map(function(img) {
var regionReduce = img.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: aoi,
scale: 10000});
return ee.Feature(aoi, regionReduce)
.set('Year', img.get('Year'));
});

// Chart mean annual temperature time series.
var chart = ui.Chart.feature.byFeature({
features:regionalTemp,
xProperty: 'Year',
yProperties: ['mean_2m_air_temperature']})
.setOptions({
title: 'Mean annual temperature',
legend: {position: 'none'},
hAxis: {title: 'Year'},
vAxis: {title: 'Kelvin'},
});
print(chart);
`````` • I'm looking to replicate this, but to calculate a global 30-year mean annual precipitation from ERA5's "total_precipitation" band instead of using temperature and creating a time-series graph. What would I have to change in the above script? May 6, 2022 at 18:24

Justin's solution is great but it works even better if you add ".distinct('year')" to the distinctYear variable (which was probably his intention).

``````// Reduce the collection to a set of unique year representatives
// to serve as the primary collection in a join with the complete
// collection.
var distinctYear = ee.ImageCollection("ECMWF/ERA5/MONTHLY")
.distinct('year');
``````

The answer is the same but the intermediate objects are one image per year instead of one per month, and the graph actually plots successfully.

• Thanks for catching the mistake in my code, Matt! I updated the answer. It was certainly was my intention to use `.distinct()` and it must have been in there at some point to get the chart image - not sure how it didn't end up in the final copy/paste and link. ¯_(ツ)_/¯ Jan 25, 2020 at 3:02