# Monthly average precipitation calculation from a GPM precipitation ImageCollection?

I want to extract the precipitation from a Image Collection and make a chart of the temporal variation of the precipitation. Can I take a single or a weighted mean of the geometry? How can I calculate the monthly precipitation? I tried following piece of code but I'm doing something wrong. How could I improve it?

``````var dataset = ee.ImageCollection('NASA/GPM_L3/IMERG_MONTHLY_V06')
.filterDate('2000', '2020');
// Select the mean precipitation values.
var precipitation = dataset.select('precipitation').mean().clip(table);
var mask = precipitation.gt(0.0);

//Calcular la Precipitación mensual
var addMonthlyPrecip = function (precipitation) {
var start = ee.Date(precipitation.get('system:time_start'));
var end = start.advance(1, 'month');
var hoursInMonth = end.difference(start, 'hours');
};
var ic = dataset.map(addMonthlyPrecip);

Map.addLayer(ic, {bands:'precip_mm_month', max: 720});

//Darle colores al mapa
var palette = [
'000096','0064ff', '00b4ff', '33db80', '9beb4a',
'ffeb00', 'ffb300', 'ff6400', 'eb1e00', 'af0000'
];

//Plotea la media de la región
var stats = precipitation.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: table,
scale: 10000,
})
print(stats.get('precipitation'))

//Imprime el numero de imagenes que se estan operando
var precipitationVis = {min: 0.0, max: 1.5, palette: palette};
//Define the chart and print it to the console.
Map.setCenter(-66.6, 1.67, 6);
//Crear grafico imageCollection(serie de tiempo)
var chart =
ui.Chart.image.series(dataset.select('precipitation'), table, ee.Reducer.mean(), 500,'system:time_start')
.setSeriesNames(['precipitacion'])
.setOptions({
title: 'Average Precipitation',
hAxis: {title: 'Date', titleTextStyle: {italic: false, bold: true}},
vAxis: {
title: 'precipitation (mm/h)',
titleTextStyle: {italic: false, bold: true}
},
lineWidth: 5,
colors: ['e37d05', '1d6b99'],
curveType: 'function'
});
print(chart);
``````

This is the link:

You don't need that kind of function in your script because is a already monthly product. However, as units in each band of precipitation are mm/hr, you have two options. One approximated assuming all months have 30 days or one more exact considering days per month (also taking in account leap years). I chose second option.

Following script has a function for multiplying each monthly values (mm/day) by month days; taking in account leap years (28 or 29 days for February). It also pairs these values with corresponding dates. I considered an arbitrary geometry (table) in USA. It looks as follows.

``````var startYear = '2001';
var endYear = '2020';

var dataset = ee.ImageCollection('NASA/GPM_L3/IMERG_MONTHLY_V06')
.filterDate(startYear, endYear)
.select('precipitation');

print(dataset);

var getPrecipit = function(image) {

// Reducing region and getting value
var value_ppt = ee.Image(image)
.reduceRegion(ee.Reducer.mean(), table)
.get('precipitation');

return ee.Number(value_ppt).multiply(24);  //mm/day

};

var count = dataset.size();

var ppt_list = dataset.toList(count).map(getPrecipit);

print("ppt_list (mm/day)", ppt_list);

var year_list = ee.List.sequence(ee.Number.parse(startYear), ee.Number.parse(endYear).subtract(1));

var leapYear_list = year_list.map( function leapYear(year) {

return ee.Number(year).mod(4).eq(0).and(ee.Number(year).mod(100).neq(0)).or(ee.Number(year).mod(400).eq(0));

});

//print(leapYear_list);

var monthNumberDays = leapYear_list.map(function (ele) {

return ee.Algorithms
.If(ee.Number(ele).eq(1), [31,29,31,30,31,30,31,31,30,31,30,31],
[31,28,31,30,31,30,31,31,30,31,30,31]);

}).flatten();

//print("Month Number Days", monthNumberDays);

var monthlyValues = ppt_list.map(function (ele){

var idx = ppt_list.indexOf(ele);

return ee.Number(ele).multiply(monthNumberDays.get(idx));

});

//print(monthlyValues);

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

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

//print(allDatesSimple);

var paired = allDatesSimple.zip(monthlyValues);

print("ppt_list (mm/month)", 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)),
'ppt_monthly':ee.Number(el.get(1))
});
}));

//print(myFeatures);

// Export features, specifying corresponding names.
Export.table.toDrive(myFeatures,
"GEE_Folder", //my export folder
"ppt_monthly",  //file name
"CSV");
``````

After running it in GEE code editor, I got result of following image; where it can be observed paired dates and monthly values in Console Tab.

• Thank you very much, with what function can I export the values ​​that the code throws to csv?? May 20, 2021 at 2:29
• You're welcome. I edited my script for including corresponding lines to export paired values as CSV file. May 20, 2021 at 2:50
• I tried to show the raster in the viewer but the variables I think are like lists, you know how I could do it to have a graphical output of my data? var palette = [ '000096','0064ff', '00b4ff', '33db80', '9beb4a', 'ffeb00', 'ffb300', 'ff6400', 'eb1e00', 'af0000'] var precipitationVis = {min: 0.0, max: 500, palette: palette}; //Define the chart and print it to the console. Map.addLayer(getPrecipit, precipitationVis, 'Precipitation'); Map.setCenter(-66.6, 1.67, 6); May 20, 2021 at 2:58

This is a more concise way of calculating the monthly precipitation based on hourly precipitation. Main difference with xunilk's answer, is that I use the 'knowledge' of GEE about dates in a function to calculate the amount of days per month. Method is inspired by a python post using datetime module I saw a long time ago.

If you get the current month and advance to the next month. Then move to the first day of that month and move 1 day to the past, you will end up on the last day of the current month, that value is of course the amount days in the current month.

``````    var startYear = '2001';
var endYear = '2020';

var dataset = ee.ImageCollection('NASA/GPM_L3/IMERG_MONTHLY_V06')
.filterDate(startYear, endYear)
.select('precipitation');

// arbitrary geometry
var geometry = ee.Geometry.Point([144.034676,-11.5905186]).buffer(5000)

// Function looks difficult, but it's just a bit messy
// It accepts a date as input and performs the following steps:
// 1. Constructs a new ee.Date using the year and month of the input date.
//    Earth Engine interprets this as [year]-[month]-01.
// 2. Advances the date to the next month.
// 3. Moves back 1 day to reach the last day of the current month.
// As a result, we obtain the number of days in the current month.
var getDaysOfMonth = function(date){
var next_mo = ee.Date(ee.String(date.get('year')).cat('-')
.cat(ee.String(date.get('month'))))
return next_mo.advance(-1, 'day' ).get('day')
}

var getPrecipit = function(image) {
// get days of month of image
var daysOfMonth = getDaysOfMonth(image.date());
// Reducing region and getting value
var value_ppt = image
.reduceRegion(ee.Reducer.mean(), geometry)
.getNumber('precipitation')
.multiply(24)
.multiply(daysOfMonth);
//return a feature with geometry null and these properties
return ee.Feature(null, {
'precipitation': value_ppt,
'system:time_start': image.date(),
'days_of_month':daysOfMonth
})
};

var pptCol = dataset.map(getPrecipit);
print(pptCol)

print(ui.Chart.feature.byFeature({
features: pptCol,
xProperty: 'system:time_start',
yProperties: ['precipitation']
}))

Map.centerObject(geometry, 13)