I would like to take the data generated in the doySeries chart and use it as an array of values. Is this at all possible? What I am interested in is using the mean over the years to create a list of cumulative precipitation values that I can then use in another chart as a reference point to identify anomalous days in later years. Below is the script I have so far:

var polygon = ee.Geometry.Polygon([[-92.56227555674951,40.858223918075275],

var startDateEarly = ee.Date('1981-01-01');
var endDateEarly = ee.Date('1983-12-31');

var chirpsColl = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY')
                .filterDate(startDateEarly, endDateEarly)

var chirpsMean = ui.Chart.image.doySeries({
  imageCollection: chirpsColl,
  region: polygon,
  scale: 1,
  yearReducer: ee.Reducer.mean(),
  //seriesProperty: 'label'

on a side note, is the scale a buffer? If so, if I set it to 0, will it only reduce within my selected region?

  • 1
    Scale is not a buffer. You can read about EE scale here: developers.google.com/earth-engine/scale Commented Feb 28, 2019 at 10:27
  • Ah, so it's just a pyramid. So that means that if I set it to 0, it will process the data in its native resolution, right?
    – IskJon
    Commented Feb 28, 2019 at 12:33
  • @RodrigoE.Principe and Kuik these are both very elaborate answers and I appreciate you taking the time to do this! I have developed an inefficient script that uses arrays to solve the problem, but I will be sure to try both solutions once I am sure my script works and does everything I want it to. This will be the next step in writing a more elegant script...
    – IskJon
    Commented Mar 4, 2019 at 8:04

2 Answers 2


Here is an approach. Take in count that the array first index is 0 and corresponds to doy 1 (first day of year)

var doySeriesArray = function(imageCollection, region, scale,
                              regionReducer, yearReducer, 
                              startDay, endDay) {
  startDay = startDay || 1
  endDay = endDay || 366
  regionReducer = regionReducer || 'mean'
  yearReducer = yearReducer || 'mean'

  // Add doy to each image in the collection
  var addDoy = function(img) {
    img = ee.Image(img)
    var doy = img.date().getRelative('day', 'year')
    doy = ee.Number(doy).add(1) // somehow gets the first day of the year as 0 and so on..
    return img.set('doy', doy)
  var withDoy = imageCollection.map(addDoy)

  // Reduce over doy
  var doys = ee.List.sequence(startDay, endDay)
  var reduceDoy = function(doy) {
    var filterDoy = withDoy.filterMetadata('doy', 'equals', doy)
    return ee.Image(filterDoy.reduce(yearReducer)).set('doy', doy)
  var reducedDoy = doys.map(reduceDoy)

  // Reduce over region
  var reduceRegion = function(img) {
    img = ee.Image(img)
    var doy = img.get('doy')
    var reduction = img.reduceRegion({
      reducer: regionReducer,
      geometry: region,
      scale: scale
    reduction = ee.Dictionary(reduction)
    return ee.Algorithms.If(reduction.contains('precipitation_mean'),

  return reducedDoy.map(reduceRegion)

var array = doySeriesArray(chirpsColl, polygon, 1)

link: https://code.earthengine.google.com/1da18e2a0341ebc14feec723a683e3c1

I have downloaded the CSV from the chart, and as far as I could see the results are the same.


Maybe you are interested in these kind of graphs, with precipitation per DOY and per year?

print(ui.Chart.image.doySeriesByYear(chirpsColl, 'precipitation', polygon, ee.Reducer.mean(), 1, ee.Reducer.mean()));

You can get the values as you have in the chart you present in your answer as:

// map over the image collection and set Doy and mean precipitation
var mapped = chirpsColl.map(function(image){
  // get the DOY
  var DOY = ee.Date(image.get('system:time_start')).format('D');
  // parse the Date output to a number
  DOY = ee.Number.parse(DOY).toInt();
  var value = image.reduceRegion(ee.Reducer.mean(), polygon, 1);
  return image.set('precMean', value.get('precipitation')).set('DOY', DOY); 

// put the values in a array. Use mean values for images with same DOY
var doys = ee.List.sequence(1,365);
var output = doys.map(function(i){
  //i = ee.Number(i).toInt();
  var valuesPerDOY = ee.List(mapped.filter(ee.Filter.eq('DOY', i)).aggregate_array('precMean'));
  var meanPrec = valuesPerDOY.reduce(ee.Reducer.mean());
  return meanPrec;

Or, if you want a dictionary output with the values of each year plus the mean value over those years, use:

// put the values in a array. Use mean values for images with same DOY
var numberOfYears = ee.Number.parse(ee.Date(chirpsColl.first().get('system:time_start')).format('yyyy')).toInt()
                      .subtract(ee.Number.parse(ee.Date(chirpsColl.sort('system:time_start', false).first().get('system:time_start')).format('yyyy')).toInt()).abs().add(1);

var doys = ee.List.sequence(1,365);
var output = doys.map(function(i){
  var valuesPerDOY = ee.List(mapped.filter(ee.Filter.eq('DOY', i)).aggregate_array('precMean'));
  // some years have 1 less day. Append zero to those lists to have similar lengths
  valuesPerDOY = ee.List(ee.Algorithms.If(valuesPerDOY.length().eq(3), valuesPerDOY, valuesPerDOY.add(0)));
  var meanPrec = ee.Number(ee.Algorithms.If(valuesPerDOY.reduce(ee.Reducer.mean()), valuesPerDOY.reduce(ee.Reducer.mean()), 0));
  return ee.Dictionary.fromLists(['1981', '1982', '1983', 'mean'], valuesPerDOY.add(meanPrec));
print('output as dictionary with years + mean',output);

Link script

  • I have tried the former script and it works very well for the area I defined. However, I would now like to look at a much bigger area where the number of pixels exceeds the 10000000 allowed by GEE. Do you know if there is a way around that?
    – IskJon
    Commented Mar 11, 2019 at 15:55
  • change the line for value to: var value = image.reduceRegion({reducer: ee.Reducer.mean(), geometry: polygon, scale: 1, maxPixels: 10e10}); It will set the maximum allowed pixels to a higher number in the reduceRegion call. Moreover, increase the scale to something like 5500, which I think approaches the native scale of 0.05 arc degrees (but search for that to make sure).
    – Kuik
    Commented Mar 11, 2019 at 18:10

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.