3

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?

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

2 Answers 2

5

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.addLayer(aoi, null, 'AOI');

// 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);

ee code editor

1
  • 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?
    – user2031
    May 6, 2022 at 18:24
3

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.

1
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.