水クラスの移行

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

このセクションでは、次の操作を行います。

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

基本的な可視化

スクリプトの [Asset List] セクションに、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 新しい永続
3 永続的な紛失
4 季節の音楽(夏うた・冬うた、など)
5 新しい季節限定
6 季節限定の損失
7 季節限定から通年
8 永続的から季節的
9 エフェメラル永続
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.pixelArea メソッドによって生成)が含まれ、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 つのヘルパー関数を作成します。ルックアップ辞書を作成するコードは、次のように [Calculations] セクションの上部に配置できます。

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

次に、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 のようになります。

水域遷移クラスの概要グラフ
図 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)をご覧ください。

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