Double loop with map() function in Google Earth Engine

孤街浪徒 提交于 2019-12-01 11:40:26

Assuming that you are just trying to understand GEE's map() function, and how would be the equivalent of a normal js for loop, the code would be:

var map_m = function(i) {
  i = ee.Number(i)
  var years = ee.List.sequence(2000, 2017)
  var filtered_col = years.map(function(j) {
    var filtered = modis.filter(ee.Filter.calendarRange(i, i, 'month'))
                        .filter(ee.Filter.calendarRange(j, j, 'year'))
    return filtered
  })
  return filtered_col
}

var months = ee.List.sequence(1, 12)
var modis_list2 = months.map(map_m).flatten()

This code replicates a normal for loop. First, it goes item by item of the years list, and then item by item of the months list, and then, once you have year and month, filter the collection and add it to a list (map does that automatically). As you use 2 map functions (one over years and the other over months), you get a list of lists, so to get a list of ImageCollection use the flatten() function. Somehow the printed objects are a bit different, but I am sure the result is the same.

The easy way to do this is with a single map over the "months" you care about.

// Collect images for each month, starting from 2000-01-01.
var months = ee.List.sequence(0, 18*12).map(function(n) {
  var start = ee.Date('2000-01-01').advance(n, 'month')
  var end = start.advance(1, 'month')
  return ee.ImageCollection("MODIS/MYD13A1").filterDate(start, end)
})
print(months.get(95))

This will return a list of ImageCollections. Most months will have only 1 image, since MYD13A1 contains 16-day images, but some will have two. Month 95 is Jan of 2008 and has two.

Alternatively, you could join the collection with a collection of dates, but this is simpler.

And you should prefer filterDate over calendarRange when possible, as it's optimized.

Let me start by saying I know nothing about Google Earth Engine and my info is from functional programming knowledge.


map is unique in that it doesn't generate the things it loops over. You start with a list and map iterates over each item in that list and transforms it. If you don't have that list then map isn't a great fit.

It looks like you are creating a list with each month/year combo represented. I would break this into a few steps. Build the month and year lists, build the list that represents cartesian product of the 2 lists then transform to the ee objects.

var range = (from, to) => new Array(end-start+1).fill(0).map((_,i)=>i+from)
var cartesianProduct = (a, b) => // not gonna do this here but it returns pairs [ [ a[1], b[1] ], ... ]
var getEE = ([month, year]) => modis
    .filter(ee.Filter.calendarRange(month, month, 'month'))
    .filter(ee.Filter.calendarRange(year, year, 'year'));

var months = range(1,12);
var years = range(2000, 2017);
var data = cartesianProduct(months, years)
    .map(getEE)

There are likely better ways(like not iterating throught the whole list of modis each time we want a single month object (use a dictionary)) but the gist is the same.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!