水クラスの移行

水遷移レイヤは、3 つの水発生クラス(水なし、季節的な水、恒久的な水)間の変化と、一時的な水(一時的な恒久的な水と一時的な季節的な水)の 2 つの追加クラスをキャプチャします。

このチュートリアルのセクションでは、次のことを行います。

  1. 水域の移り変わりを可視化するマップレイヤを追加
  2. 指定された対象地域内の各遷移クラスの面積を合計するグループ化されたリデューサーを作成します。
  3. 遷移クラス別に面積をまとめたグラフを作成します。

基本的な可視化

スクリプトの [アセット リスト] セクションで、transition という単一バンド画像オブジェクトを作成する次のステートメントを追加します。

コードエディタ(JavaScript)

var transition = gsw.select('transition');

GSW 画像には、遷移クラスの番号と名前に関するメタデータと、遷移クラスのスタイル設定用のデフォルト パレットが含まれています。移行レイヤが地図に追加されると、これらの可視化パラメータが自動的に使用されます。

スクリプトの [Map Layers] セクションの下部に、次のステートメントを追加します。これにより、トランジション クラスを表示する新しい地図レイヤが追加されます。

コードエディタ(JavaScript)

Map.setCenter(105.26, 11.2134, 9);     // Mekong River Basin, SouthEast Asia
Map.addLayer({
  eeObject: transition,
  name: 'Transition classes (1984-2015)',
});

スクリプトを実行すると、トランジション レイヤが表示されます。

地表水移行クラス
図 10. メコン川デルタのスクリーンショット。地表水クラスの移行に大きなばらつきがあることがわかる。

移行クラスのマップキーは次のとおりです。

記号 ラベル
0 水ではない
1 永続的
2 New permanent
3 Lost permanent
4 季節の音楽
5 新しい季節性
6 季節限定のアイテムを紛失した
7 季節限定から定番へ
8 永続的なものから季節的なものへ
9 Ephemeral permanent
10 エフェメラル シーズナル

移行クラス別のエリアの概要

このセクションでは、再びジオメトリ ポリゴン ツールを使用して対象地域を定義します。新しい場所を分析する場合は、まず描画した元のポリゴンを選択して削除し、結合されたエリアの結果が表示されないようにします。ジオメトリの変更方法については、コードエディタのドキュメントの ジオメトリ ツールのセクションをご覧ください。

この例では、メコン川デルタ内に新しいポリゴンを描画します。

ROI を伴う移行クラス
図 11. ベトナムのメコン川デルタ。コードエディタのポリゴン描画ツールを使用して作成された対象地域。

画像の一部で覆われている面積を計算するために、 ee.Image.pixelArea メソッドを使用して、各ピクセルのサイズを平方メートルで識別する追加のバンドをトランジション画像オブジェクトに追加します。

コードエディタ(JavaScript)

var area_image_with_transition_class = ee.Image.pixelArea().addBands(transition);

結果の画像オブジェクト(area_image_with_transition_class)は 2 バンド画像です。最初のバンドには面積情報( ee.Image.pixelAreacode> メソッドで生成)が平方メートル単位で含まれ、2 番目のバンドには遷移クラス情報が含まれます。

次に、 ee.Image.reduceRegion メソッドと、各遷移クラス内の面積を合計するグループ化されたリデューサーを使用して、対象領域(roi)内のクラス遷移を要約します。

コードエディタ(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 が表示されます。エリアの概要データを表示するには、ツリーを数レベル展開する必要があります。

グループ化された削減結果
図 12. コンソール タブの出力。グループ化された削減の結果が表示されています。

reduction_results オブジェクトには各トランジション クラスがカバーする領域に関する情報が含まれていますが、読み取りは容易ではありません。次のセクションでは、結果を簡単に確認できるようにします。

概要グラフの作成

このセクションでは、結果をより適切に要約するグラフを作成します。まず、次のように領域を含む遷移クラスのリストを抽出します。

コードエディタ(JavaScript)

var roi_stats = ee.List(reduction_results.get('groups'));

グループ化されたリデューサー(reduction_results)の結果は、辞書のリストを含む辞書です。リストには、各トランジション クラスに対応する辞書が 1 つずつあります。これらのステートメントは、 ee.Dictionary.get メソッドを使用して、グループ化されたリデューサーの結果を辞書から抽出し、結果を ee.List データ型にキャストして、個々の辞書にアクセスできるようにします。

コードエディタのグラフ作成関数を利用するために、必要な情報を含む FeatureCollection を作成します。これを行うために、まず 2 つのルックアップ ディクショナリと 2 つのヘルパー関数を作成します。ルックアップ辞書を作成するコードは、次のように [計算] セクションの先頭に配置できます。

コードエディタ(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 辞書は、遷移クラスの値を色の定義に関連付けます。

2 つのヘルパー関数は、「ヘルパー関数」という新しいコード セクションに配置できます。

コードエディタ(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 は、円グラフで想定される形式を使用して、遷移クラスに対応する色のリストを作成します。

次に、ee.List.map を使用して、リスト(roi_stats)内の各ディクショナリに createFeature 関数を適用し、リストの各要素にヘルパー関数を適用します。

コードエディタ(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 のようになります。

水分の移行クラスの概要グラフ
図 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 データセットで利用可能なデータレイヤのうち、3 つ(発生、変化の強さ、移行)のみを操作する方法について説明しました。利用可能な他のデータレイヤについては、 データ ユーザー ガイド(v2)をご覧ください。

ご利用をお待ちしております。