1

I'm trying to categorize temperature extremes for a region. Using the Hycom GEE dataset, I know that using a Reducer I can find the maximum value for each pixel across the image collection (see code below). However, I'd like to find that top 10 or 15 temperatures across each pixel in the collection and average them together to characterize a swath of the hottest days that year. It doesn't look like you can specify how many of the max values you want with ee.Reducer.max(). I'm really new to GEE coding so I'm stumped. How can I get the i number of maximum values?

var dataset = ee.ImageCollection('HYCOM/sea_temp_salinity')
                  .filter(ee.Filter.date('2019-01-01', '2019-12-30'))
                  .filter(ee.Filter.neq('system:index','2017022312'))
                  .filter(ee.Filter.neq('system:index','2019030509'))
var temp_0 = dataset.select('water_temp_0', 'salinity_0');
var max = temp_0.reduce(ee.Reducer.max())

1 Answer 1

2

Earth Engine does not currently have a "N greatest/least values" reducer. Without that, our remaining option is to use sorting, which has the disadvantage of requiring the entire collection to be brought into memory.

To get it to succeed I reduced your date range to the first six months:

var dataset = ee.ImageCollection('HYCOM/sea_temp_salinity')
                  .filter(ee.Filter.date('2019-01-01', '2019-06-30'))
                  .filter(ee.Filter.neq('system:index','2017022312'))
                  .filter(ee.Filter.neq('system:index','2019030509'));

Then, in order to do per-pixel sorting, we need to convert the collection into an array image (one image, each pixel in each band being a time series):

var temp_0_array = dataset.select('water_temp_0', 'salinity_0').toArrayPerBand();

Now, if you want just the average of the highest temperatures, you can sort them and take the last 10:

var ten_hottest_values = temp_0_array
    .select('water_temp_0')
    .arraySort()
    .arraySlice({start: -10});
var average = ten_hottest_values.arrayReduce(ee.Reducer.mean(), [0]);
Map.addLayer(average);

However, I guess from your .select('water_temp_0', 'salinity_0') that you might want to work with the salinity values corresponding to those temperatures. If so, then you can sort all the array bands using the temperature as the sort ordering like so:

var ten_hottest_values = temp_0_array
    .arraySort(temp_0_array.select('water_temp_0'))
    .arraySlice({start: -10});

But that will be a more expensive computation, so don't do it unless you need it.

https://code.earthengine.google.com/92ba786a02ae0e6f0c058e8b5781ed88


You may also be interested in ee.Reducer.intervalMean(); it does not take the mean of exactly 10 or 15 values, but the mean of values falling in a percentile range, which you can (if you wish) adjust to get approximately 10 values knowing the size of the collection. It will be significantly more efficient than the sorting approach above, but cannot do the "sorting salinity by temperature" computation if you want that.

var temp_0 = dataset.select('water_temp_0', 'salinity_0');
Map.addLayer(temp_0.reduce(ee.Reducer.intervalMean(90, 100)));
1
  • Kevin, thank you for this! I think the IntervalMean Reducer will work best for my purposes. Very neat to see the other method as well, as it expands my understanding of the kinds of things I can do in GEE. Sep 17, 2020 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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