1

I am trying to create a chart showing the number of images per year from an ImageCollection of Landsat images but I can't seems to find a solution for it (my ImageCollection consists of Landsat images from Landsat 4 - 9 from 1988 - 2022).

If possible, I also would like to have the information of which Landsat collection the images are belonging to on the x-axis as well. My goal is to have a chart similar to this chart below:

My objective

How can I make such a chart?

2 Answers 2

5

You will be unable to get Google Chart API to make a dual-axis chart like that. For complex charting, your best option is to extract the data and do the charting in another tool. You can get the number of images per year by mapping over the images and setting a year property on each one, and then doing a reduceColumns on the collection with a histogram reducer:

var data = collection
  .map(function(img) {
    return img.set('year', img.date().get('year'))
  })
  .reduceColumns(ee.Reducer.frequencyHistogram(), ["year"])

But that's likely to go pretty slow since it's completely sequential. Alternatively, you can map over the years and filter the collection to each year. That should be faster since it can run the years in parallel.

var data = ee.List.sequence(1984, 2023)
  .map(function(y) {
    var start = ee.Date.fromYMD(y, 1, 1)
    var end = start.advance(1, 'year')
    // Return a list of [key, value] so we can turn them all into a dictionary
    return [start.format("Y"), collection.filterDate(start, end).size()]
  }).flatten()
data = ee.Dictionary(data)

But, in both cases, your result might take long enough to compute that you need to run it as an export, in which case, just stick the resulting dictionary into a feature and export it.

Export.table.toDrive(ee.FeatureCollection(ee.Feature(null, data)), "data export")
0
0

Gorelick,

Thank you for your reply and the suggestion to solve my problem. In addition to your answer, I have also come up with a solution based on the script provided in this URL: https://code.earthengine.google.com/e95b7ebd9ecf4f5f35133fbb12638722

Below I present my script


/* -------------------------- Study region -----------------------------*/
var study_region = ee.FeatureCollection('path/to/aoi/shapefile/');

var empty = ee.Image().byte();
var region_draw = empty.paint({
  featureCollection: study_region,
  color: 1,
  width: 3
});

Map.addLayer(region_draw, {palette: 'red'}, 'study_region');
Map.centerObject(study_region);


/* ---------------------- Customize Parameters -------------------------*/
var yStart = 1988;
var yEnd = 2022;

var listYears = ee.List.sequence(yStart, yEnd, 1);


/* ----------------------- Get Landsat images --------------------------*/

var featCol = ee.FeatureCollection(listYears.map(function(year){
  // set start and end date from the year
  var start_date = ee.Date.fromYMD(year, 1, 1);
  var end_date = ee.Date.fromYMD(ee.Number(year).add(1), 1, 1);
  var start_day = 1;
  var end_day = 365;

  var collection4 = ee.ImageCollection('LANDSAT/LT04/C02/T1_L2')
    .filterBounds(study_region)
    .filterDate(start_date, end_date)
    .filter(ee.Filter.dayOfYear(start_day,end_day));

  var collection5 = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2')
    .filterBounds(study_region)
    .filterDate(start_date, end_date)
    .filter(ee.Filter.dayOfYear(start_day,end_day));
  
  var collection7 = ee.ImageCollection('LANDSAT/LE07/C02/T1_L2')
    .filterBounds(study_region)
    .filterDate(start_date, end_date)
    .filter(ee.Filter.dayOfYear(start_day,end_day));

  var collection8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterBounds(study_region)
    .filterDate(start_date, end_date)
    .filter(ee.Filter.dayOfYear(start_day,end_day));

  var collection9 = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2')
    .filterBounds(study_region) //Use the same mask for Landsat 9*/
    .filterDate(start_date, end_date)
    .filter(ee.Filter.dayOfYear(start_day,end_day));
  
  var LS4_size = collection4.size();
  var LS5_size = collection5.size();
  var LS7_size = collection7.size();
  var LS8_size = collection8.size();  
  var LS9_size = collection9.size();  
  
  // Return the size in a feature
  var feature = ee.Feature(ee.Geometry.Point([0,0]), {
    year:ee.Number(year).format('%d'), 'system:time_start':start_date.millis(),
    LS4: LS4_size, LS5: LS5_size, LS7: LS7_size, LS8: LS8_size, LS9: LS9_size});

  return feature;
}));


/* ---------------------- Create the chart -------------------------*/

// plot as a chart
var chart = ui.Chart.feature.byFeature(
  featCol, 'year', ['LS4', 'LS5', 'LS7', 'LS8', 'LS9'])
    .setChartType('ColumnChart').setOptions( {
      title: 'Number of observations and their according Landsat collection from the ImageCollection',
      isStacked: true, bar: {groupWidth: '95%'},
      legend: { position: 'in'},
      vAxis: {title: 'Number of Observations'}, 
      hAxis: {title: 'Year', }, 
    })
    .setSeriesNames(['Landsat-4', 'Landsat-5', 'Landsat-7', 'Landsat-8', 'Landsat-9']);

print(chart); 
print('Feature Collection', featCol);

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.