# Calculating daily GDD from ERA-5 Hourly data

I have written a code for calculating GDD(Growing Degree Days) using the ERA-5 hourly 2m temperature data in Google Earth Engine. The code uses the max and min temperature of that day to calculate the average temperature which is then subtracted by the base temperature (which is a constant value). The code works fine for a single date data, however when I try to replicate it for a month, I either get a single value for all days or hourly values which is incorrect. I have to carry out this analysis day wise for an entire year, hence I cannot run the code for each day individually. I have tried many methods to replicate the code for a longer time period but none of them are giving me results.

To summarize following are the objectives I wish to achieve with my code:

1. Replicate the GDD formula for each day in a month
2. Extract GDD value and export in .csv format with the date and GDD value

How can I achieve these objectives?

``````// Create a geometry representing an export region.
var StudyArea = ee.Geometry.Rectangle([76.134,28.7472,76.394, 28.486]);
Map.centerObject(StudyArea)
var roi = ee.Geometry.Rectangle([76.302,28.602,76.317,28.593]);
var image = ee.ImageCollection("ECMWF/ERA5_LAND/HOURLY")
.filter(ee.Filter.date('2021-01-01','2021-01-02'))
//.filter(ee.Filter.eq('hour', 17))
.filterBounds(StudyArea)
.select('temperature_2m');

///////////////////////Calculation of GDD///////////////////////////////////////
var cgdd = function(image){
var min = image.min()
var min1 = min.clip(StudyArea)
var max = image.max()
var max1 = max.clip(StudyArea)
var a = ee.Image(2)
var avg = sum.divide(a)
var b = ee.Image(273)
var celcius= avg.subtract(b)
var c = ee.Image(17.9)
var gdd = celcius.subtract(c).rename('GDD');
return gdd;
};

// Test the function on a single image.
var test = cgdd(image);
print(test)

// Extracting the values for ROI
var extract = test.reduceRegions({
collection: roi,
reducer: ee.Reducer.mean(),
scale: 10,
});

print(extract)

``````

You need to create a list with the dates and run a server-side mapping (run your calculation for every object in that list). I would than filter the collection taking the date that was passed to the function from the list and advancing it by one day: `var image = ic.filterDate(date, ee.Date(date).advance(1, "day"))`

Something like this:

``````  var dates = ee.List.sequence(1, 365).map(function(day){
})
print(dates)

var ic =   ee.ImageCollection("ECMWF/ERA5_LAND/HOURLY")
.filterBounds(StudyArea)
.select('temperature_2m');
var res = dates.map(function(date){
var image = ic.filterDate(date, ee.Date(date).advance(1, "day"))
var min = image.min()
var min1 = min.clip(StudyArea)
var max = image.max()
var max1 = max.clip(StudyArea)
var a = ee.Image(2)
var avg = sum.divide(a)
var b = ee.Image(273)
var celcius= avg.subtract(b)
var c = ee.Image(17.9)
var gdd = celcius.subtract(c).rename('GDD');
var gdd_reduced = gdd.reduceRegion({
geometry: roi,
reducer: ee.Reducer.mean(),
scale: 10
}).get("GDD")

return ee.Feature(null).set(ee.Dictionary({"date": date, "GDD": gdd_reduced}))
}).flatten()

print("calculation result per day", res)
Export.table.toDrive(ee.FeatureCollection(res))
``````

Alternatively, you could also create the list with starting and ending dates and map the function over that list.

Also, the scale of the data is >10km, no need for you to use 10m scale.

The approach of accepted answer produces cgd values that begins with -2.6887802124023423 value instead your only produced value for cgd of -6.731283569335936. For this reason, I used a very different approach for obtaining daily values, by ussing a 24 images list in a function, to find out this apparently anomaly. My code looks as follows.

``````// Create a geometry representing an export region.
var StudyArea = ee.Geometry.Rectangle([76.134,28.7472,76.394, 28.486]);

Map.centerObject(StudyArea);

var roi = ee.Geometry.Rectangle([76.302,28.602,76.317,28.593]);
var col = ee.ImageCollection("ECMWF/ERA5_LAND/HOURLY")
.filter(ee.Filter.date('2021-01-01','2022-01-01'))
.filterBounds(StudyArea)
.select('temperature_2m');

print('scale', col.first().projection().nominalScale());

var col_lst = col.toList(col.size());
var len = col.size();

print(col_lst);

var list = ee.List.sequence(0, len.subtract(1), 24);

var new_list = list.map(function(img){

var start = ee.Number(img).int();

var new_list = ee.List([]);
var element = ee.List(col_lst.slice(start, end));

var min = ee.ImageCollection(new_list.flatten()).min();
var max = ee.ImageCollection(new_list.flatten()).max();

var gdd = ee.Image().expression(
'(((min + max)/2) - 273) - 17.9', {
'min': min,
'max': max,
}).rename('GDD');

// Extracting the values for ROI
var value = gdd.reduceRegion(ee.Reducer.mean(), roi, 10000).get('GDD');

return value;

});

print(new_list);

var allDates = ee.List(col.aggregate_array('system:time_start'));

var allDatesSimple = allDates.map(function(date){
return ee.Date(date).format().slice(0,10);
}).distinct();

//print(allDatesSimple);

var paired = allDatesSimple.zip(new_list);

//print (paired);

var myFeatures = ee.FeatureCollection(paired.map(function(el){
el = ee.List(el); // cast every element of the list

return ee.Feature(null, {
'date': ee.String(el.get(0)),
'gdd value':ee.Number(el.get(1))
});
}));

//print(myFeatures);

// Export features, specifying corresponding names.
Export.table.toDrive(myFeatures,