2

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);
var precipitation = precipitation.updateMask(mask);

//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');
  return precipitation.addBands(precipitation.multiply(hoursInMonth).rename('precip_mm_month'));
};
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};
//Map.addLayer(clipped05, colorizedVis, 'NDVI');
//Define the chart and print it to the console.
Map.addLayer(precipitation, precipitationVis, 'Precipitation');
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:

https://code.earthengine.google.com/71b2c0ffc4ead42aefd1d769ae7b86f6

2 Answers 2

1

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,
"export_ppt", //my task
"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.

enter image description here

3
  • 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.
    – xunilk
    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
0

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.

Link to script

    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'))))
      .advance(1, '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)
    Map.addLayer(geometry)

enter image description here

Your Answer

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

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