0

I defined a polygon

var polygon = ee.Geometry.Polygon([114, 0.37, 114, 2.04, 112, 2.04, 112, 0.37]);

and a dataset that needs to be processed for the above polygon

var dataset = ee.ImageCollection('NASA/NEX-GDDP');

for a selected date

var startDate = ee.Date('1980-01-01');
var endDate = ee.Date('1980-01-02');

The dataset has 3 bands pr, tasmax and tasmin and I am selecting the one that I need to process

var dataset = ee.ImageCollection('NASA/NEX-GDDP')
             .filter(ee.Filter.date(startDate,endDate))
             .filter(ee.Filter.bounds(polygon))
             .select('tasmax');


Map.addLayer(dataset)

I want to export the data for all the grids falling under the polygon along with their respective lat long. Since there are 21 features (GCMs) for a single day, I am expecting the final data to have number rows equal to number of grids in polygon X 21 features (GCMs)

var dailyImg = dataset.toBands();

Export.table.toDrive({
    collection: dailyImg,
    description: 'hist_tx',
    fileFormat: 'CSV',
});

When I try to do this, I get an error

Error: Invalid argument: 'collection' must be a FeatureCollection.

How can I solve this? In addition, even after restricting my spatial area to the polygon, the map still displays the data for the entire globe? Why is this happening?

nicola
  • 24,005
  • 3
  • 35
  • 56
89_Simple
  • 3,393
  • 3
  • 39
  • 94

1 Answers1

1

Error: Invalid argument: 'collection' must be a FeatureCollection.

Export.table is for exporting tables, also known as FeatureCollections. You have an image, not a table.

The most efficient way to get the data out of Earth Engine is to use Export.image instead, then convert the downloaded GeoTIFF to suit your R program. However, since this dataset is very small, downloading it as a CSV will work fine, and the tool for that is ee.Image.sample which converts a region of an Image to a FeatureCollection.

var collection = dailyImg.sample({
  region: polygon,
  geometries: true,  // This specifies that you want the lat-long, rather
                     // than image samples without any position information.
});

If you export this, you will get the position in a single column in GeoJSON format. That's probably not what you want, so we can convert it to columns:

var collection_with_latlon = collection.map(function (feature) {
  var coordinates = feature.geometry().transform('epsg:4326').coordinates();
  return feature.set('lon', coordinates.get(0), 'lat', coordinates.get(1));
});

Here's everything put together as a working example:

var polygon = ee.Geometry.Polygon([114, 0.37, 114, 2.04, 112, 2.04, 112, 0.37]);
var startDate = ee.Date('1980-01-01');
var endDate = ee.Date('1980-01-02');
var dataset = ee.ImageCollection('NASA/NEX-GDDP')
             .filter(ee.Filter.date(startDate,endDate))
             .filter(ee.Filter.bounds(polygon))
             .select('tasmax');

Map.addLayer(polygon);

var dailyImg = dataset.toBands();
var collection = dailyImg.sample({
  region: polygon,
  geometries: true,  // This specifies that you want the lat-long.
});

// Break point coordinates up into properties (table columns) explicitly.
var collection_with_latlon = collection.map(function (feature) {
  var coordinates = feature.geometry().transform('epsg:4326').coordinates();
  return feature.set('lon', coordinates.get(0), 'lat', coordinates.get(1));
});

print(collection_with_latlon);

Export.table.toDrive({
    collection: collection_with_latlon,
    description: 'hist_tx',
    fileFormat: 'CSV',
});

In addition, even after restricting my spatial area to the polygon, the map still displays the data for the entire globe? Why is this happening?

Filtering a collection to geometry only omits images that do not intersect the geometry. In this case, the images cover the entire globe, so no images are filtered out. In order to clip the images to the collection you would have to specify that, e.g.:

var dailyImg = dataset.toBands().clip(polygon);

However, this is not necessary if you are using .sample(), because that operation has its own region parameter and will not use any pixels outside the polygon.

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
  • Thank you. This is very useful and I learnt a lot following your code. I had a follow up question. Is it possible to have days and lat long both as rows. For each if I have 10 days, then I will have number of rows = 10 * number of cells and each column is the corresponding feature/ – 89_Simple Aug 19 '20 at 00:36
  • @89_Simple That's a fairly substantial question and if you need more help you should post it separately (not in comments) but the short version is that whenever you want to "multiply" the number of features like that, it's going to use `FeatureCollection.flatten`, looking somewhat like `collectionOfCells.map(function(cell) { return collectionOfDays.map(function (day) { /* now compute the feature you want to have based on cell and day */ }); }).flatten()` — first you use `map` inside `map` to construct a collection of collections, then `flatten` to turn it into one big collection. – Kevin Reid Aug 19 '20 at 01:01
  • thank you @Kevin. I will post it as a separate question. Meanwhile I will use your comment reply to work out myself. – 89_Simple Aug 19 '20 at 01:09