将具有未知键的字典转换为地球引擎中的特征集合
Convert a dictionary with unknown keys to Feature collection in Earh engine
我在转换 sampleRegion
在 Earth Engine
中返回的某些 ee.Dictionary
(具有空值键)时遇到问题。我正在尝试跨多个区域对多波段图像进行采样,然后将生成的字典转换为 ee.FeatureCollection
,其中 key/value 对(字典的)将是具有 null
几何特征的特征。我想保留所有键,包括具有 null
值的键。具有 null
值的键应重新编码为 9 或保留为 null
,但我需要将它们作为最终集合中的特征。我尝试使用 ee.Algorithms.If
来处理这些具有 null
值的键,但我得到堆栈并出现以下错误:
FeatureCollection (Error)
Error in map(ID=0): Element.geometry, argument 'feature': Invalid type. Expected type: Element. Actual type: String. Actual value: B3
下面是一个可重现的例子,也可以找到 here。任何提示都会有很大帮助!
// Some features to use latter in sampleRegion
var roi1 =
/* color: #d63000 */
/* shown: false */
/* displayProperties: [
{
"type": "rectangle"
},
{
"type": "rectangle"
},
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.2850232278161755, 14.924433184708537],
[1.2850232278161755, 14.741234323298656],
[1.4882702981286755, 14.741234323298656],
[1.4882702981286755, 14.924433184708537]]], null, false),
{
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[1.4772839700036755, 14.04155518401385],
[1.4772839700036755, 13.86296344675159],
[1.6393323098474255, 13.86296344675159],
[1.6393323098474255, 14.04155518401385]]], null, false),
{
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[1.0817761575036755, 14.478114793660426],
[1.0817761575036755, 14.313173466470698],
[1.2767834817224255, 14.313173466470698],
[1.2767834817224255, 14.478114793660426]]], null, false),
{
"system:index": "2"
})]),
roi2 =
/* color: #98ff00 */
/* displayProperties: [
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.6970105325036755, 14.448859913271122],
[1.6970105325036755, 14.25994066279539],
[1.9387097512536755, 14.25994066279539],
[1.9387097512536755, 14.448859913271122]]], null, false),
{
"system:index": "0"
})]),
roi3 =
/* color: #0b4a8b */
/* displayProperties: [
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.7739148293786755, 14.38501773168985],
[1.7739148293786755, 14.29188185649032],
[1.8755383645349255, 14.29188185649032],
[1.8755383645349255, 14.38501773168985]]], null, false),
{
"rec": 3,
"system:index": "0"
})]);
// Getting the image of the region of interest
var roi = ee.Geometry.Point([1.864578244475683, 14.492292970253338]);
var image = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2019-01-01', '2019-01-31')
.filterBounds(roi)
.select(['B5', 'B4', 'B3'])
.toBands()
.rename(['B5', 'B4', 'B3']);
// Checking it out
print(image);
// Define the visualization parameters.
var vizParams = {
bands: ['B5', 'B4', 'B3'],
min: 0,
max: 0.5,
gamma: [0.95, 1.1, 1]
};
// Center the map and display the image.
Map.centerObject(image, 9);
Map.addLayer(image, vizParams, 'image');
// masking out some regions from the
// image, so that sampleRegion will return null in that region
var mask = ee.Image.constant(1).clip(roi2).mask().not()
var imageMasked = image.updateMask(mask);
// displaying the masked image
Map.addLayer(imageMasked, vizParams, 'imageMasked');
/////////// The actual problem start from here ///////////
// making a feature collection (masked + unmasked region)
var roi = roi1.merge(roi3);
var regionSamples = roi.map(function(x){
var out = imageMasked.reduceRegion({
reducer : ee.Reducer.mean().unweighted(),
geometry : x.geometry(),
scale : 30
})
// Getting the keys of the dictionary returned by sampleRegion
var keys = out.keys()
// mapping a function over the list of
// keys to latter extract their corresponding values
var keyVals = keys.map(function(y){
var proba = ee.Algorithms.If({
// test if the value corresponding to a key is null
condition: ee.Algorithms.IsEqual(out.get(y), null),
// if it the case, return a feature with property prob set to 9
trueCase: ee.Feature(null, {prob: 9}),
// if it not the case, return a feature with property prob
// set the value return by sampleRegion
falseCase: ee.Feature(null, {prob: out.get(y)})
})
return proba
})
return ee.FeatureCollection(keyVals)
})
print(regionSamples.flatten(), 'regional samples')
我终于弄明白了,我发布了答案以防有人感兴趣。我使用以下功能解决了这些问题。
/////////// The actual problem start from here ///////////
/**
* Reduce multiple regions of an image to feature collection.
* @param {Image} The image to reduce.
* @param {FeatureCollection} roi The area/areas of interest.
* @param {Float} scale A nominal scale in meters of the projection to work in.
* @param {Float} nullKeyValue The value to use for keys where reduceRegion returns null.
* @return {FeatureCollection} A feature collection where dictionary keys returned by reduceRegion are converted to ee.Feature.
*/
function sampleFeatures(image, roi, nullKeyValue, scale){
var keyVals = roi.map(function(x){
var dictionary = image.reduceRegion({
reducer : ee.Reducer.mean().unweighted(),
geometry : x.geometry(),
scale : scale
})
var noNullDic = dictionary.map(function(key, val){
var dic = ee.Algorithms.If({
condition: ee.Algorithms.IsEqual(val, null),
trueCase: nullKeyValue,
falseCase: dictionary.get(key)
})
return dic;
});
var keys = noNullDic.keys()
var vals = keys.map(function(key){
var vl = ee.List([noNullDic.get(key)])
var ky = ee.List([key])
return ee.Feature(null, ee.Dictionary.fromLists(ky, vl))
})
return ee.FeatureCollection(vals)
})
return keyVals.flatten()
}
var test = sampleFeatures(imageMasked, roi, 999, 30)
print(test, 'test sampleFeatures')
我在转换 sampleRegion
在 Earth Engine
中返回的某些 ee.Dictionary
(具有空值键)时遇到问题。我正在尝试跨多个区域对多波段图像进行采样,然后将生成的字典转换为 ee.FeatureCollection
,其中 key/value 对(字典的)将是具有 null
几何特征的特征。我想保留所有键,包括具有 null
值的键。具有 null
值的键应重新编码为 9 或保留为 null
,但我需要将它们作为最终集合中的特征。我尝试使用 ee.Algorithms.If
来处理这些具有 null
值的键,但我得到堆栈并出现以下错误:
FeatureCollection (Error) Error in map(ID=0): Element.geometry, argument 'feature': Invalid type. Expected type: Element. Actual type: String. Actual value: B3
下面是一个可重现的例子,也可以找到 here。任何提示都会有很大帮助!
// Some features to use latter in sampleRegion
var roi1 =
/* color: #d63000 */
/* shown: false */
/* displayProperties: [
{
"type": "rectangle"
},
{
"type": "rectangle"
},
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.2850232278161755, 14.924433184708537],
[1.2850232278161755, 14.741234323298656],
[1.4882702981286755, 14.741234323298656],
[1.4882702981286755, 14.924433184708537]]], null, false),
{
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[1.4772839700036755, 14.04155518401385],
[1.4772839700036755, 13.86296344675159],
[1.6393323098474255, 13.86296344675159],
[1.6393323098474255, 14.04155518401385]]], null, false),
{
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[1.0817761575036755, 14.478114793660426],
[1.0817761575036755, 14.313173466470698],
[1.2767834817224255, 14.313173466470698],
[1.2767834817224255, 14.478114793660426]]], null, false),
{
"system:index": "2"
})]),
roi2 =
/* color: #98ff00 */
/* displayProperties: [
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.6970105325036755, 14.448859913271122],
[1.6970105325036755, 14.25994066279539],
[1.9387097512536755, 14.25994066279539],
[1.9387097512536755, 14.448859913271122]]], null, false),
{
"system:index": "0"
})]),
roi3 =
/* color: #0b4a8b */
/* displayProperties: [
{
"type": "rectangle"
}
] */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[1.7739148293786755, 14.38501773168985],
[1.7739148293786755, 14.29188185649032],
[1.8755383645349255, 14.29188185649032],
[1.8755383645349255, 14.38501773168985]]], null, false),
{
"rec": 3,
"system:index": "0"
})]);
// Getting the image of the region of interest
var roi = ee.Geometry.Point([1.864578244475683, 14.492292970253338]);
var image = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2019-01-01', '2019-01-31')
.filterBounds(roi)
.select(['B5', 'B4', 'B3'])
.toBands()
.rename(['B5', 'B4', 'B3']);
// Checking it out
print(image);
// Define the visualization parameters.
var vizParams = {
bands: ['B5', 'B4', 'B3'],
min: 0,
max: 0.5,
gamma: [0.95, 1.1, 1]
};
// Center the map and display the image.
Map.centerObject(image, 9);
Map.addLayer(image, vizParams, 'image');
// masking out some regions from the
// image, so that sampleRegion will return null in that region
var mask = ee.Image.constant(1).clip(roi2).mask().not()
var imageMasked = image.updateMask(mask);
// displaying the masked image
Map.addLayer(imageMasked, vizParams, 'imageMasked');
/////////// The actual problem start from here ///////////
// making a feature collection (masked + unmasked region)
var roi = roi1.merge(roi3);
var regionSamples = roi.map(function(x){
var out = imageMasked.reduceRegion({
reducer : ee.Reducer.mean().unweighted(),
geometry : x.geometry(),
scale : 30
})
// Getting the keys of the dictionary returned by sampleRegion
var keys = out.keys()
// mapping a function over the list of
// keys to latter extract their corresponding values
var keyVals = keys.map(function(y){
var proba = ee.Algorithms.If({
// test if the value corresponding to a key is null
condition: ee.Algorithms.IsEqual(out.get(y), null),
// if it the case, return a feature with property prob set to 9
trueCase: ee.Feature(null, {prob: 9}),
// if it not the case, return a feature with property prob
// set the value return by sampleRegion
falseCase: ee.Feature(null, {prob: out.get(y)})
})
return proba
})
return ee.FeatureCollection(keyVals)
})
print(regionSamples.flatten(), 'regional samples')
我终于弄明白了,我发布了答案以防有人感兴趣。我使用以下功能解决了这些问题。
/////////// The actual problem start from here ///////////
/**
* Reduce multiple regions of an image to feature collection.
* @param {Image} The image to reduce.
* @param {FeatureCollection} roi The area/areas of interest.
* @param {Float} scale A nominal scale in meters of the projection to work in.
* @param {Float} nullKeyValue The value to use for keys where reduceRegion returns null.
* @return {FeatureCollection} A feature collection where dictionary keys returned by reduceRegion are converted to ee.Feature.
*/
function sampleFeatures(image, roi, nullKeyValue, scale){
var keyVals = roi.map(function(x){
var dictionary = image.reduceRegion({
reducer : ee.Reducer.mean().unweighted(),
geometry : x.geometry(),
scale : scale
})
var noNullDic = dictionary.map(function(key, val){
var dic = ee.Algorithms.If({
condition: ee.Algorithms.IsEqual(val, null),
trueCase: nullKeyValue,
falseCase: dictionary.get(key)
})
return dic;
});
var keys = noNullDic.keys()
var vals = keys.map(function(key){
var vl = ee.List([noNullDic.get(key)])
var ky = ee.List([key])
return ee.Feature(null, ee.Dictionary.fromLists(ky, vl))
})
return ee.FeatureCollection(vals)
})
return keyVals.flatten()
}
var test = sampleFeatures(imageMasked, roi, 999, 30)
print(test, 'test sampleFeatures')