Google Earth Engine – How to Calculate NDVI Landsat 5 Time Series for Multiple Polygons

csvgoogle-earth-enginendvi

I'm trying to calculate the average NDVI of each polygon existing within my shapefile.

  • I generated code that calculates the NDVI for each available date for the Landsat 5 image.

  • Afterwards, this code calculates the average of the pixels of each polygon existing inside my shapefile.

  • Finally it generates a CSV spreadsheet and exports.

My problem is that it generates the spreadsheet, but the column with the average was left with empty values.

roi = https://drive.google.com/file/d/10PPDluM81cppJtJhqKXH-f1H0Jg192oi/view?usp=sharing

//Study area
//the area has three divisions according to the "nome_imo" column: fazenda_1, fazenda_2 and fazenda_3
//I want to calculate the NDVI mean of each of the divisions over time
//and generate a spreadsheet with 
//the image date, division name and ndvi mean value

var roi = ee.FeatureCollection('users/wesleysc352/area_fazenda')
  .filter(ee.Filter.or(ee.Filter.eq('nome_imo', 'fazenda_1'),
                       ee.Filter.eq('nome_imo', 'fazenda_2'),
                       ee.Filter.eq('nome_imo', 'fazenda_3')));

//image collection
var L5 = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
 .filterMetadata('CLOUD_COVER', 'less_than', 1)
 .filterDate('2011-01-01','2011-12-31')


//Calculate NDVI
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B3', 'B4']);
  return image.addBands(ndvi);
};

//aplly ndvi for collection
var L5_ndvi = L5.map(addNDVI)

//create fuction for change date for system yyyy-MM-dd
function date_edit (image) { 
     return image.set({date_edit:image.date().format('yyyy-MM-dd')})}

//aplly date_edit for collection
var NDVI_data = L5_ndvi.map(date_edit);

//create spreadsheet
var feats = NDVI_data.map(function(image){

  var stats = image.clip(roi).reduceRegions({
    collection: roi,
    reducer:ee.Reducer.mean(),
    scale:30
})

stats = stats.map(function(f) { return f.set({date_edit: image.get('date_edit')})})
return stats.copyProperties(image, ['system:time_start'])
})

//generating the columns
var NDVI_mean = feats.flatten()
.select(['date_edit', 'nome_imo','mean']);

//map center
Map.centerObject(roi, 11)


//Export data
Export.table.toDrive({
collection: NDVI_mean,
description: 'CSV_Export',
folder: 'GEE_teste',
fileNamePrefix: 'NDVI_mean',//name file
fileFormat: 'CSV',
selectors: ['nome_imo','date_edit', 'mean']
});

output csv file without column "mean"

enter image description here

Best Answer

Your code have several issues. Main of them was in NDVI definition from L5 data. B3 and B4 bands were inverted for NDVI determination producing senseless negative values. You can corroborate that in this link. So, I modified your code as follows and, after running it in GEE Code Editor, values (nome_imo, date_edit and mean) were exported to Google Drive as expected CSV. I commented .filterMetadata line for obtaining more NDVI values. CLOUD_COVER less_than 1 is a very drastic restriction and it only produces three values per feature in considered data range.

//Study area
//the area has three divisions according to the "nome_imo" column: fazenda_1, fazenda_2 and fazenda_3
//I want to calculate the NDVI mean of each of the divisions over time
//and generate a spreadsheet with 
//the image date, division name and ndvi mean value

var roi = ee.FeatureCollection('users/joseguerreroa/area_fazenda')
  .filter(ee.Filter.or(ee.Filter.eq('nome_imo', 'fazenda_1'),
                       ee.Filter.eq('nome_imo', 'fazenda_2'),
                       ee.Filter.eq('nome_imo', 'fazenda_3')));

//print(roi);

//image collection
var L5 = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
  //.filterMetadata('CLOUD_COVER', 'less_than', 1)
  .filterDate('2011-01-01','2011-12-31')
  .filterBounds(roi);

//Calculate NDVI
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B4', 'B3'])
                  .rename('ndvi');
  return image.addBands(ndvi);
};

//aplly ndvi for collection
var L5_ndvi = L5.map(addNDVI);

print("count", L5_ndvi.size());

var L5_ndvi_list = L5_ndvi.toList(L5_ndvi.size());

var L5_ndvi = L5_ndvi.select(['ndvi']);

//print("L5_ndvi", L5_ndvi);

var L5_ndviVis = {
  min: 0.15348,
  max: 0.76315,
};

Map.addLayer(L5_ndvi, L5_ndviVis, 'L5_ndvi');
Map.addLayer(roi);
Map.centerObject(roi, 12);

var feats_list = roi.toList(roi.size());

var ndvi_values = feats_list.map(function (feat) {
  
  var ndvi_val = L5_ndvi_list.map(function (image) {
  
  var stats = ee.Image(image).reduceRegion(
    {reducer: ee.Reducer.mean(),
     geometry: ee.Feature(feat).geometry()});
  
    return [ee.Feature(feat).get('nome_imo'), ee.Date(ee.Image(image).get('system:time_start')).format('yyyy-MM-dd'), stats.get('ndvi')];
  
  });
  
  return ndvi_val;
  
}).flatten();

//print("ndvi_values", ndvi_values);

var len = ndvi_values.size();

var list = ee.List.sequence(0, len.subtract(1), 3);

var new_ndvi_values = list.map(function(ele){

  var start = ee.Number(ele).int(); 
  var end = ee.Number(ele).add(3).int(); 

  var new_list = ee.List([]);
  var element = ee.List(ndvi_values.slice(start, end));

  new_list = new_list.add(element);

  return new_list.get(0);

});

//print (new_ndvi_values);

var myFeatures = ee.FeatureCollection(new_ndvi_values.map(function(el){
  el = ee.List(el); // cast every element of the list

  return ee.Feature(null, {
    'nome_imo': el.get(0),
    'date_edit': el.get(1),
    'mean': el.get(2)
  });
}));

//print(myFeatures);

// Export features, specifying corresponding names.
Export.table.toDrive(myFeatures,
"CSV_Export", //my task
"GEE_teste", //my export folder
"NDVI_mean",  //file name
"CSV");

After running above code, general NDVI raster image and roi area were loaded in Map Canvas of GEE; as it can be observed in following image.

enter image description here

Produced CSV file can be observed as follows opened in LibreOffice Calc. It can be edited for deleting not desired fields and for expressing a different order fields.

enter image description here