0

I am struggling to convert a javascript earth engine routine to python which is taken from this material here

The javascript is as follows I have included the input collections for context.

var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
    .filterBounds(roi)
    .filterDate('2016-01-01', '2016-12-31');

// Load an Earth Engine table.
var blocks = ee.FeatureCollection('TIGER/2010/Blocks');
var subset = blocks.filterBounds(roi);
print('Size of Census blocks subset', subset.size()); // 409


var triplets = l8.map(function(image) {
  return image.select('B1').reduceRegions({
    collection: subset.select(['blockid10']), 
    reducer: ee.Reducer.mean(), 
    scale: 30
  }).filter(ee.Filter.neq('mean', null))
    .map(function(f) { 
      return f.set('imageId', image.id());
    });
}).flatten();

The part I am a bit stuck on is the conversion of the variable triplets, which includes various nested routines. My python version returns the error:

Unrecognized argument type to convert to a FeatureCollection: {'collection': <ee.featurecollection.FeatureCollection object at 0x7f29fb0e2b80>, 'reducer': <ee.Reducer object at 0x7f29fb10e670>, 'scale': 30}

The issue seems to be map(imfunc), which I assume is down to me getting the python function wrong.

def imfunc(image):
  return image.select('B1').reduceRegions({
    'collection': subset.select(['blockid10']),
    'reducer': ee.Reducer.mean(),
    'scale': 30})

def wrapf(f):
    return f.set('imageId', image.id())

triplets = l8.map(imfunc).filter(ee.Filter.neq('mean', {})).map(wrapf).flatten()

Can anyone shed light on where I am going wrong with the python conversion?

crEO
  • 89
  • 5

1 Answers1

1

In the original code, .filter(...).map(wrapf) is applied to the result of reduceRegions. In your translated code, you have instead applied it to the result of l8.map(), the outer collection instead of the inner, because you didn't keep it inside the outer map function.

This is a corrected translation:

def imfunc(image):
  return (image.select('B1')
    .reduceRegions(
      collection=subset.select(['blockid10']),
      reducer=ee.Reducer.mean(),
      scale=30
    )
    .filter(ee.Filter.neq('mean', None))
    .map(wrapf))

def wrapf(f):
    return f.set('imageId', image.id())

triplets = l8.map(imfunc).flatten()

I also fixed the arguments to reduceRegions to use Python-style named arguments instead of a dictionary (this is necessary). There may be other errors I didn't fix — I haven't tested this code — but I hope it helps with learning how to translate.

Note that you don't need to change every function to a named function. Instead of .map(wrapf) you can use .map(lambda f: f.set('imageId', image.id())))

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
  • Thanks very much - the wrapf does not work, but the anon. lambda function does - I tried to edit your answer but it does not appear to have worked/been approved. – crEO Apr 22 '21 at 11:46
  • @crEO It should be equivalent as written, so something else is going on with the actual code you ran. What error do you see with it? (Your edit was [rejected by reviewers](https://stackoverflow.com/review/suggested-edits/28801139).) – Kevin Reid Apr 22 '21 at 15:24