Слой перехода воды фиксирует изменения между тремя классами наличия воды (не вода, сезонная вода и постоянная вода), а также двумя дополнительными классами для эфемерных вод (эфемерно-постоянная и эфемерно-сезонная).
В этом разделе руководства будут:
- добавить слой карты для визуализации перехода воды,
- создать групповой редуктор для суммирования площади каждого переходного класса в указанной интересующей области и
- создать диаграмму, суммирующую территорию по переходным классам.
Базовая визуализация
В разделе «Список активов» скрипта добавьте следующий оператор, который создает однополосный объект изображения с именем transition
:
Редактор кода (JavaScript)
var transition = gsw.select('transition');
Изображения GSW содержат метаданные о номерах и названиях классов переходов, а также палитру по умолчанию для оформления классов переходов. При добавлении слоя переходов на карту эти параметры визуализации будут использоваться автоматически.
В нижней части раздела «Слои карты» вашего скрипта добавьте следующий оператор, который добавляет новый слой карты, отображающий классы перехода:
Редактор кода (JavaScript)
Map.setCenter(105.26, 11.2134, 9); // Mekong River Basin, SouthEast Asia Map.addLayer({ eeObject: transition, name: 'Transition classes (1984-2015)', });
При запуске скрипта будет отображен переходный слой.

Ключ карты для классов перехода:
Ценить | Символ | Этикетка |
---|---|---|
0 | Не вода | |
1 | Постоянный | |
2 | Новый постоянный | |
3 | Потерянный постоянный | |
4 | Сезонный | |
5 | Новый сезонный | |
6 | Потерянный сезонный | |
7 | От сезонного до постоянного | |
8 | Постоянный или сезонный | |
9 | Эфемерный постоянный | |
10 | Эфемерный сезонный |
Подведение итогов по переходному классу
В этом разделе мы снова воспользуемся инструментом «Геометрический многоугольник» для определения интересующей области. Если вы хотите проанализировать новое местоположение, сначала выберите и удалите исходный нарисованный вами многоугольник, чтобы не получить результаты, связанные с объединёнными областями. Подробнее об изменении геометрии см. в разделе «Геометрические инструменты» документации по редактору кода.
В этом примере мы нарисуем новый многоугольник в дельте реки Меконг.

Чтобы рассчитать площадь, занимаемую частями изображения, мы добавим к объекту переходного изображения дополнительную полосу, которая идентифицирует размер каждого пикселя в квадратных метрах, используя метод ee.Image.pixelArea .
Редактор кода (JavaScript)
var area_image_with_transition_class = ee.Image.pixelArea().addBands(transition);
Полученный объект изображения ( area_image_with_transition_class
) представляет собой двухполосное изображение, где первая полоса содержит информацию о площади в квадратных метрах (созданную методом ee.Image.pixelArea
code> ), а вторая полоса содержит информацию о классе перехода.
Затем мы суммируем переходы классов в интересующей области ( roi
), используя метод ee.Image.reduceRegion
и групповой редуктор , который суммирует область в каждом классе перехода:
Редактор кода (JavaScript)
var reduction_results = area_image_with_transition_class.reduceRegion({ reducer: ee.Reducer.sum().group({ groupField: 1, groupName: 'transition_class_value', }), geometry: roi, scale: 30, bestEffort: true, }); print('reduction_results', reduction_results);
На вкладке консоли теперь отображается значение reduction_results
. Обратите внимание, что для просмотра сводных данных по площади потребуется развернуть дерево на несколько уровней.

Хотя объект reduction_results
содержит информацию об области, охватываемой каждым классом перехода, его не очень удобно читать. В следующем разделе мы упростим просмотр результатов.
Создание сводной диаграммы
В этом разделе мы составим диаграмму для более наглядного представления результатов. Для начала составим список переходных классов с областями следующим образом:
Редактор кода (JavaScript)
var roi_stats = ee.List(reduction_results.get('groups'));
Результатом работы сгруппированного редуктора ( reduction_results
) является словарь, содержащий список словарей. В списке для каждого класса перехода имеется один словарь. Эти операторы используют метод ee.Dictionary.get для извлечения сгруппированных результатов редуктора из этого словаря и приведения их к типу данных ee.List , что позволяет получить доступ к отдельным словарям.
Чтобы использовать функции построения диаграмм в редакторе кода , мы создадим коллекцию FeatureCollection, содержащую необходимую информацию. Для этого сначала создадим два словаря поиска и две вспомогательные функции. Код, создающий словари поиска, можно разместить в верхней части раздела «Вычисления» следующим образом:
Редактор кода (JavaScript)
////////////////////////////////////////////////////////////// // Calculations ////////////////////////////////////////////////////////////// // Create a dictionary for looking up names of transition classes. var lookup_names = ee.Dictionary.fromLists( ee.List(gsw.get('transition_class_values')).map(numToString), gsw.get('transition_class_names') ); // Create a dictionary for looking up colors of transition classes. var lookup_palette = ee.Dictionary.fromLists( ee.List(gsw.get('transition_class_values')).map(numToString), gsw.get('transition_class_palette') );
Словарь lookup_names
связывает значения классов перехода с их именами, тогда как словарь lookup_palette
связывает значения классов перехода с определениями цветов.
Две вспомогательные функции можно поместить в новый раздел кода под названием «Вспомогательные функции». Редактор кода (JavaScript)
//////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////
// Create a feature for a transition class that includes the area covered.
function createFeature(transition_class_stats) {
transition_class_stats = ee.Dictionary(transition_class_stats);
var class_number = transition_class_stats.get('transition_class_value');
var result = {
transition_class_number: class_number,
transition_class_name: lookup_names.get(class_number),
transition_class_palette: lookup_palette.get(class_number),
area_m2: transition_class_stats.get('sum')
};
return ee.Feature(null, result); // Creates a feature without a geometry.
}
// Create a JSON dictionary that defines piechart colors based on the
// transition class palette.
// https://developers.google.com/chart/interactive/docs/gallery/piechart
function createPieChartSliceDictionary(fc) {
return ee.List(fc.aggregate_array("transition_class_palette"))
.map(function(p) { return {'color': p}; }).getInfo();
}
// Convert a number to a string. Used for constructing dictionary key lists
// from computed number objects.
function numToString(num) {
return ee.Number(num).format();
}
Функция createFeature
принимает словарь (содержащий площадь и класс перехода воды) и возвращает объект Feature, подходящий для построения диаграммы. Функция createPieChartSliceDictionary
создаёт список цветов, соответствующих классам перехода, используя формат, ожидаемый круговой диаграммой.
Далее мы применим функцию createFeature
к каждому словарю в списке ( roi_stats
), используя ee.List.map для применения вспомогательной функции к каждому элементу списка.
Редактор кода (JavaScript)
var transition_fc = ee.FeatureCollection(roi_stats.map(createFeature)); print('transition_fc', transition_fc);
Теперь, когда у нас есть FeatureCollection, содержащий атрибуты, которые мы хотим отобразить на диаграмме, мы можем создать объект диаграммы и вывести его на консоль.
Редактор кода (JavaScript)
// Add a summary chart. var transition_summary_chart = ui.Chart.feature.byFeature({ features: transition_fc, xProperty: 'transition_class_name', yProperties: ['area_m2', 'transition_class_number'] }) .setChartType('PieChart') .setOptions({ title: 'Summary of transition class areas', slices: createPieChartSliceDictionary(transition_fc), sliceVisibilityThreshold: 0 // Don't group small slices. }); print(transition_summary_chart);
Параметр slices
раскрашивает сегменты круговой диаграммы так, чтобы они использовали палитру по умолчанию, заданную для классов перехода (показанную ранее в таблице ключей карты). Параметр sliceVisibilityThreshold
предотвращает объединение небольших сегментов в категорию «другое». Результирующая диаграмма должна быть похожа на ту, что показана на рисунке 13.

Финальный сценарий
Полный сценарий этого раздела такой:
Редактор кода (JavaScript)
////////////////////////////////////////////////////////////// // Asset List ////////////////////////////////////////////////////////////// var gsw = ee.Image('JRC/GSW1_0/GlobalSurfaceWater'); var occurrence = gsw.select('occurrence'); var change = gsw.select("change_abs"); var transition = gsw.select('transition'); var roi = ee.Geometry.Polygon( [[[105.531921, 10.412183], [105.652770, 10.285193], [105.949401, 10.520218], [105.809326, 10.666006]]]); ////////////////////////////////////////////////////////////// // Constants ////////////////////////////////////////////////////////////// var VIS_OCCURRENCE = { min: 0, max: 100, palette: ['red', 'blue'] }; var VIS_CHANGE = { min: -50, max: 50, palette: ['red', 'black', 'limegreen'] }; var VIS_WATER_MASK = { palette: ['white', 'black'] }; ////////////////////////////////////////////////////////////// // Helper functions ////////////////////////////////////////////////////////////// // Create a feature for a transition class that includes the area covered. function createFeature(transition_class_stats) { transition_class_stats = ee.Dictionary(transition_class_stats); var class_number = transition_class_stats.get('transition_class_value'); var result = { transition_class_number: class_number, transition_class_name: lookup_names.get(class_number), transition_class_palette: lookup_palette.get(class_number), area_m2: transition_class_stats.get('sum') }; return ee.Feature(null, result); // Creates a feature without a geometry. } // Create a JSON dictionary that defines piechart colors based on the // transition class palette. // https://developers.google.com/chart/interactive/docs/gallery/piechart function createPieChartSliceDictionary(fc) { return ee.List(fc.aggregate_array("transition_class_palette")) .map(function(p) { return {'color': p}; }).getInfo(); } // Convert a number to a string. Used for constructing dictionary key lists // from computed number objects. function numToString(num) { return ee.Number(num).format(); } ////////////////////////////////////////////////////////////// // Calculations ////////////////////////////////////////////////////////////// // Create a dictionary for looking up names of transition classes. var lookup_names = ee.Dictionary.fromLists( ee.List(gsw.get('transition_class_values')).map(numToString), gsw.get('transition_class_names') ); // Create a dictionary for looking up colors of transition classes. var lookup_palette = ee.Dictionary.fromLists( ee.List(gsw.get('transition_class_values')).map(numToString), gsw.get('transition_class_palette') ); // Create a water mask layer, and set the image mask so that non-water areas // are transparent. var water_mask = occurrence.gt(90).mask(1); // Generate a histogram object and print it to the console tab. var histogram = ui.Chart.image.histogram({ image: change, region: roi, scale: 30, minBucketWidth: 10 }); histogram.setOptions({ title: 'Histogram of surface water change intensity.' }); print(histogram); // Summarize transition classes in a region of interest. var area_image_with_transition_class = ee.Image.pixelArea().addBands(transition); var reduction_results = area_image_with_transition_class.reduceRegion({ reducer: ee.Reducer.sum().group({ groupField: 1, groupName: 'transition_class_value', }), geometry: roi, scale: 30, bestEffort: true, }); print('reduction_results', reduction_results); var roi_stats = ee.List(reduction_results.get('groups')); var transition_fc = ee.FeatureCollection(roi_stats.map(createFeature)); print('transition_fc', transition_fc); // Add a summary chart. var transition_summary_chart = ui.Chart.feature.byFeature({ features: transition_fc, xProperty: 'transition_class_name', yProperties: ['area_m2', 'transition_class_number'] }) .setChartType('PieChart') .setOptions({ title: 'Summary of transition class areas', slices: createPieChartSliceDictionary(transition_fc), sliceVisibilityThreshold: 0 // Don't group small slices. }); print(transition_summary_chart); ////////////////////////////////////////////////////////////// // Initialize Map Location ////////////////////////////////////////////////////////////// // Uncomment one of the following statements to center the map on // a particular location. // Map.setCenter(-90.162, 29.8597, 10); // New Orleans, USA // Map.setCenter(-114.9774, 31.9254, 10); // Mouth of the Colorado River, Mexico // Map.setCenter(-111.1871, 37.0963, 11); // Lake Powell, USA // Map.setCenter(149.412, -35.0789, 11); // Lake George, Australia Map.setCenter(105.26, 11.2134, 9); // Mekong River Basin, SouthEast Asia // Map.setCenter(90.6743, 22.7382, 10); // Meghna River, Bangladesh // Map.setCenter(81.2714, 16.5079, 11); // Godavari River Basin Irrigation Project, India // Map.setCenter(14.7035, 52.0985, 12); // River Oder, Germany & Poland // Map.setCenter(-59.1696, -33.8111, 9); // Buenos Aires, Argentina // Map.setCenter(-74.4557, -8.4289, 11); // Ucayali River, Peru ////////////////////////////////////////////////////////////// // Map Layers ////////////////////////////////////////////////////////////// Map.addLayer({ eeObject: water_mask, visParams: VIS_WATER_MASK, name: '90% occurrence water mask', shown: false }); Map.addLayer({ eeObject: occurrence.updateMask(occurrence.divide(100)), name: "Water Occurrence (1984-2015)", visParams: VIS_OCCURRENCE, shown: false }); Map.addLayer({ eeObject: change, visParams: VIS_CHANGE, name: 'occurrence change intensity', shown: false }); Map.addLayer({ eeObject: transition, name: 'Transition classes (1984-2015)', });
На этом завершается руководство по набору данных Global Surface Water. Обратите внимание, что в этом руководстве показано, как работать только с тремя слоями данных (появление, интенсивность изменений и переход), доступными в наборе данных Global Surface Water. Подробнее о других слоях данных можно узнать в Руководстве пользователя данных (версия 2) .
Приятного анализа!