Search code examples
google-earth-engine

Google Earth Engine: Extract second largest value from annual observations?


In Google Earth Engine, is it possible to extract the annual second largest and second smallest value and construct an imagecollection? Apparently, there is no build-in reducer for this purpose. Here is my code for getting the min, please guide me on how to get the second max and min. Thank you!

Here is the code:

var startDate = ee.Date('2001-01-01'); // set start time for analysis
var endDate = ee.Date('2021-12-31'); // set end time for analysis

// calculate the number of year to process
var nyears = ee.Number(endDate.difference(startDate,'year'));

//init a time band
var createTimeBand= function(image) {
  return image.addBands(image.metadata('system:time_start')
  .divide(1e18))
 // .divide(1000*60*60*24*365))
}


var sst = ee.ImageCollection('MODIS/006/MOD11A1').select('LST_Day_1km')
            .filterDate(startDate, endDate)
            .map(createTimeBand)

var byyearMin = ee.ImageCollection(
  // map over each month
  ee.List.sequence(0,nyears).map(function (n) {
    // calculate the offset from startDate
    var ini = startDate.advance(n,'year');
    // advance just one month
    var end = ini.advance(1,'year');
    // filter and reduce
    return sst.filterDate(ini,end)
                .select(0).min()
              //  .sort('LST_Day_1km').reverse().first()
                .multiply(0.02)
                .subtract(273.15)
                .set('system:time_start', ini.millis());//convert time to number
}));

Solution

  • var startDate = ee.Date('2001-01-01'); // set start time for analysis
    var endDate = ee.Date('2021-12-31'); // set end time for analysis
    
    // calculate the number of year to process
    var nyears = ee.Number(endDate.difference(startDate,'year'));
    
    //init a time band
    var createTimeBand= function(image) {
      return image.addBands(image.metadata('system:time_start')
      .divide(1e18))
     // .divide(1000*60*60*24*365))
    }
    
    
    var sst = ee.ImageCollection('MODIS/006/MOD11A1').select('LST_Day_1km')
                .filterDate(startDate, endDate)
                //.map(createTimeBand)
                
    var byyearMin = ee.ImageCollection(
      // map over each month
      ee.List.sequence(0,nyears).map(function (n) {
        // calculate the offset from startDate
        var ini = startDate.advance(n,'year');
        // advance just one month
        var end = ini.advance(1,'year');
        
        var sortedDays = sst.filterDate(ini,end)
        .sort('LST_Day_1km')
        .toList(sst.size())
          
        var secondLargest = ee.List(sortedDays.get(1))
        var secondSmallest = ee.List(sortedDays.get(-1))
        
        var collection = ee.Image(secondLargest)
        .addBands(secondSmallest).rename(['secondLargest', 'secondSmallest'])
        .multiply(0.02)
          .subtract(273.15)
          return collection
          .set('system:time_start', ini.millis()) //convert time to number
          .set('Date', ee.Date(ini))
    }));
    
    print(byyearMin)