[GIS] LinearRegression with Google Earth Engine

google-earth-enginemodisndvi

I ve been doing simple linear regressions with GEE and I have found a possible error that I would like to share and in case that I am wrong, please let me know:

Is it possible that when LinearRegressions function is used, GEE always takes equidistant distances in the independent variable(x)?

I ve tried to do regressions with NDVI (y) and time (x) and GEE always takes the same distance between observations and it is not true because between images(dates) there is no the same distance, sometimes are 1 day but sometimes are 3, 10 or whatever.

Does anyone know how to introduce the real distance between independent variable?

For example: image1 (from 1st of January), image2 (from 2nd of January), image3 (from 10 of February) would be: 1-2-10 instead of 1-2-3 (what GEE does).

The code is as follows:

// Simple regression of year versus SAVI.

// Define the start date and position to get images covering TDPS,
// Bolivia, from 2000-2010.
var start = '2000-01-01';
var end = '2014-12-31';

var region = table4


// Filter to Collection
// time of year to avoid seasonal affects, and for each image create the bands
// we will regress on:
// 1. A 1, so the resulting array has a column of ones to capture the offset.
// 2. Fractional year past 2000-01-01.
// 3. SAVI.

var col = ee.ImageCollection("MODIS/MOD13Q1")
  .filterDate(start, end)
  .filter(ee.Filter.calendarRange(1,1,'month'))
  .filterBounds(region)
  .map(function(image) {
    var date = ee.Date(image.get('system:time_start'));
    var yearOffset = date.difference(ee.Date(start), 'year');
    var savi = image.expression(
      '(1 + L) * float(nir - red)/ (nir + red + L)',
      {
        'nir': image.select('sur_refl_b02'),
        'red': image.select('sur_refl_b01'),
        'L': 0.5
      });
    return ee.Image(1).addBands(yearOffset).addBands(savi).toDouble();
  });

print(col)
// Convert to an array. Give the axes names for more readable code.
var array = col.toArray();
var imageAxis = 0;
var bandAxis = 1;

// Slice off the year and savi, and solve for the coefficients.
var x = array.arraySlice(bandAxis, 0, 2);
var y = array.arraySlice(bandAxis, 2);
var fit = x.matrixSolve(y).clip(region);

// Get the coefficient for the year, effectively the slope of the long-term
// SAVI trend.
var slope = fit.arrayGet([1, 0]).clip(region);

Map.addLayer(slope);

// Export the image, specifying scale and region.
Export.image.toDrive({
  image: slope,
  description: 'SAVI_slope_jan_MODIS_00_14',
  scale: 250,
  maxPixels: 1e9,
  region: geometry
});

Best Answer

Add a time-band to your images before doing the linear fit. See docs on regression.

// This function adds a time band to the image.
var createTimeBand = function(image) {
  // Scale milliseconds by a large constant to avoid very small slopes
  // in the linear regression output.
  return image.addBands(image.metadata('system:time_start').divide(1e18));
};
Related Question