DataTable 차트

ui.Chart 함수는 Google 차트 DataTable 클래스와 동일한 구조를 따르지만 DataTable 메서드와 변경 불가능성이 없는 클라이언트 측 JSON 객체에서 차트를 렌더링합니다. 관측을 나타내는 행과 관측 속성을 나타내는 열이 있는 2차원 표입니다. Earth Engine에서 차트를 표시하기 위한 유연한 기본 인터페이스를 제공합니다. 고도의 차트 맞춤설정이 필요한 경우에 적합합니다.

스키마 DataTable

Earth Engine에서 가상 DataTable를 정의하는 방법에는 JavaScript 2D 배열과 JavaScript 리터럴 객체라는 두 가지가 있습니다. 대부분의 애플리케이션의 경우 2D 배열을 구성하는 것이 가장 간단한 접근 방식입니다. 두 경우 모두 ui.Chart에 전달된 테이블은 클라이언트 측 객체여야 합니다. 수동으로 코딩된 테이블은 본질적으로 클라이언트 측에 있지만 계산된 객체는 evaluate를 사용하여 클라이언트 측으로 전송해야 합니다. 서버 측 객체와 클라이언트 측 객체의 차이점에 관한 자세한 내용은 클라이언트와 서버 비교 페이지를 참고하세요.

JavaScript 배열

2D DataTable는 행과 열 배열로 구성됩니다. 행은 관측치이고 열은 속성입니다. 첫 번째 열은 x축의 값을 정의하고 추가 열은 y축 계열의 값을 정의합니다. 첫 번째 행은 열 헤더여야 합니다. 가장 간단한 헤더는 일련의 열 라벨로, 선택한 주별 인구를 나타내는 다음 배열 DataTable에서 볼 수 있습니다.

var dataTable = [
  ['State', 'Population'],
  ['CA', 37253956],
  ['NY', 19378102],
  ['IL', 12830632],
  ['MI', 9883640],
  ['OR', 3831074],
];

원하는 경우 열을 도메인(x축) 및 데이터(y축 계열) 정의 이외의 역할(예: 주석, 간격, 도움말, 스타일)에 지정할 수 있습니다. 다음 예에서는 헤더 배열이 일련의 객체로 표시되며 여기서 각 열의 역할이 명시적으로 정의됩니다. 각 Google 차트 유형에 허용되는 열 역할은 해당 문서(예: 열 차트 데이터 형식)에서 확인할 수 있습니다.

var dataTable = [
  [{role: 'domain'}, {role: 'data'}, {role: 'annotation'}],
  ['CA', 37253956, '37.2e6'],
  ['NY', 19378102, '19.3e6'],
  ['IL', 12830632, '12.8e6'],
  ['MI', 9883640, '9.8e6'],
  ['OR', 3831074, '3.8e6'],
];

열 속성은 다음과 같이 지정됩니다.

매개변수 유형 정의
type 문자열, 권장 열 데이터 유형: 'string', 'number', 'boolean', 'date', 'datetime' 또는 'timeofday'
label 문자열, 권장 차트 범례의 열 라벨, 계열 라벨입니다.
role 문자열, 권장 열의 역할 (예: 열 차트의 역할)
pattern 문자열(선택사항) 열 값을 표시하는 방법을 지정하는 숫자 (또는 날짜) 형식 문자열입니다.

JavaScript 객체

DataTable는 행 및 열 객체의 배열이 제공되는 JavaScript 리터럴 객체 형식으로 지정할 수 있습니다. 열 및 행 매개변수를 지정하는 방법은 이 가이드를 참고하세요.

var dataTable = {
  cols: [{id: 'name', label: 'State', type: 'string'},
         {id: 'pop', label: 'Population', type: 'number'}],
  rows: [{c: [{v: 'CA'}, {v: 37253956}]},
         {c: [{v: 'NY'}, {v: 19378102}]},
         {c: [{v: 'IL'}, {v: 12830632}]},
         {c: [{v: 'MI'}, {v: 9883640}]},
         {c: [{v: 'OR'}, {v: 3831074}]}]
};

수동 DataTable 차트

차트에 표시할 소량의 정적 데이터가 있다고 가정해 보겠습니다. JavaScript 배열 또는 객체 사양을 사용하여 ui.Chart 함수에 전달할 입력을 생성합니다. 여기에서는 2010년 미국 인구 조사에서 선택한 주 인구가 열 속성을 정의하는 열 헤더 객체가 포함된 JavaScript 배열로 인코딩됩니다. 세 번째 열은 'annotation' 역할로 지정되어 인구를 차트의 각 관측값에 주석으로 추가합니다.

코드 편집기 (JavaScript)

// Define a DataTable using a JavaScript array with a column property header.
var dataTable = [
  [
    {label: 'State', role: 'domain', type: 'string'},
    {label: 'Population', role: 'data', type: 'number'},
    {label: 'Pop. annotation', role: 'annotation', type: 'string'}
  ],
  ['CA', 37253956, '37.2e6'],
  ['NY', 19378102, '19.3e6'],
  ['IL', 12830632, '12.8e6'],
  ['MI', 9883640, '9.8e6'],
  ['OR', 3831074, '3.8e6']
];

// Define the chart and print it to the console.
var chart = ui.Chart(dataTable).setChartType('ColumnChart').setOptions({
  title: 'State Population (US census, 2010)',
  legend: {position: 'none'},
  hAxis: {title: 'State', titleTextStyle: {italic: false, bold: true}},
  vAxis: {title: 'Population', titleTextStyle: {italic: false, bold: true}},
  colors: ['1d6b99']
});
print(chart);

계산된 DataTable 차트

DataTable 배열은 서버에서 evaluate를 통해 클라이언트로 전달된 2D ee.List에서 만들 수 있습니다. 일반적인 시나리오는 ee.FeatureCollection, ee.ImageCollection의 속성 또는 이러한 속성의 요소별 감소를 DataTable로 변환하는 것입니다. 다음 예에 적용된 전략은 주어진 요소를 줄이는 ee.ImageCollection에 함수를 매핑하고, 감소 결과에서 ee.List를 조합하고, 목록을 'row'라는 속성으로 반환된 요소에 연결합니다. 새 컬렉션의 각 요소에는 DataTable의 행을 나타내는 1차원 ee.List가 있습니다. aggregate_array() 함수는 모든 'row' 속성을 상위 ee.List로 집계하여 DataTable에 필요한 도형으로 2D 서버 측 ee.List를 만드는 데 사용됩니다. 맞춤 열 헤더가 테이블에 연결되고 결과는 evaluate를 사용하여 클라이언트 측으로 전송되며 여기서 ui.Chart 함수를 사용하여 렌더링됩니다.

지역별 시계열

이 예는 숲이 우거진 생태 지역의 MODIS 파생 NDVI 및 EVI 식물 지수 시계열을 보여줍니다. 계열의 각 이미지는 생태 지역별로 축소되고 결과는 'row' 속성으로 조합되며, 이 속성은 클라이언트에게 전달하고 ui.Chart로 차트 표시하기 위해 DataTable로 집계됩니다. 이 스니펫은 ui.Chart.image.series 차트 예시에서 생성된 것과 동일한 차트를 생성합니다.

코드 편집기 (JavaScript)

// Import the example feature collection and subset the forest feature.
var forest = ee.FeatureCollection('projects/google/charts_feature_example')
                 .filter(ee.Filter.eq('label', 'Forest'));

// Load MODIS vegetation indices data and subset a decade of images.
var vegIndices = ee.ImageCollection('MODIS/061/MOD13A1')
                     .filter(ee.Filter.date('2010-01-01', '2020-01-01'))
                     .select(['NDVI', 'EVI']);

// Define a function to format an image timestamp as a JavaScript Date string.
function formatDate(img) {
  var millis = img.date().millis().format();
  return ee.String('Date(').cat(millis).cat(')');
}

// Build a feature collection where each feature has a property that represents
// a DataFrame row.
var reductionTable = vegIndices.map(function(img) {
  // Reduce the image to the mean of pixels intersecting the forest ecoregion.
  var stat = img.reduceRegion(
      {reducer: ee.Reducer.mean(), geometry: forest, scale: 500});

  // Extract the reduction results along with the image date.
  var date = formatDate(img);   // x-axis values.
  var evi = stat.get('EVI');    // y-axis series 1 values.
  var ndvi = stat.get('NDVI');  // y-axis series 2 values.

  // Make a list of observation attributes to define a row in the DataTable.
  var row = ee.List([date, evi, ndvi]);

  // Return the row as a property of an ee.Feature.
  return ee.Feature(null, {'row': row});
});

// Aggregate the 'row' property from all features in the new feature collection
// to make a server-side 2-D list (DataTable).
var dataTableServer = reductionTable.aggregate_array('row');

// Define column names and properties for the DataTable. The order should
// correspond to the order in the construction of the 'row' property above.
var columnHeader = ee.List([[
  {label: 'Date', role: 'domain', type: 'date'},
  {label: 'EVI', role: 'data', type: 'number'},
  {label: 'NDVI', role: 'data', type: 'number'}
]]);

// Concatenate the column header to the table.
dataTableServer = columnHeader.cat(dataTableServer);

// Use 'evaluate' to transfer the server-side table to the client, define the
// chart and print it to the console.
dataTableServer.evaluate(function(dataTableClient) {
  var chart = ui.Chart(dataTableClient).setOptions({
    title: 'Average Vegetation Index Value by Date for Forest',
    hAxis: {
      title: 'Date',
      titleTextStyle: {italic: false, bold: true},
    },
    vAxis: {
      title: 'Vegetation index (x1e4)',
      titleTextStyle: {italic: false, bold: true}
    },
    lineWidth: 5,
    colors: ['e37d05', '1d6b99'],
    curveType: 'function'
  });
  print(chart);
});

간격 차트

이 차트는 DataTable'role' 속성을 활용하여 간격 차트를 생성합니다. 이 차트는 캘리포니아 몬테레이 근처의 픽셀에 대한 연간 NDVI 프로필과 연간 간 변동성을 보여줍니다. 연간 중앙값은 선으로 표시되고 절대값 및 중앙값 간격은 밴드로 표시됩니다. 각 간격을 나타내는 테이블 열은 'role' 열 속성을 'interval'로 설정하여 할당됩니다. intervals.style 차트 속성을 'area'로 설정하여 중앙선 주위에 밴드가 그려집니다.

코드 편집기 (JavaScript)

// Define a point to extract an NDVI time series for.
var geometry = ee.Geometry.Point([-121.679, 36.479]);

// Define a band of interest (NDVI), import the MODIS vegetation index dataset,
// and select the band.
var band = 'NDVI';
var ndviCol = ee.ImageCollection('MODIS/006/MOD13Q1').select(band);

// Map over the collection to add a day of year (doy) property to each image.
ndviCol = ndviCol.map(function(img) {
  var doy = ee.Date(img.get('system:time_start')).getRelative('day', 'year');
  // Add 8 to day of year number so that the doy label represents the middle of
  // the 16-day MODIS NDVI composite.
  return img.set('doy', ee.Number(doy).add(8));
});

// Join all coincident day of year observations into a set of image collections.
var distinctDOY = ndviCol.filterDate('2013-01-01', '2014-01-01');
var filter = ee.Filter.equals({leftField: 'doy', rightField: 'doy'});
var join = ee.Join.saveAll('doy_matches');
var joinCol = ee.ImageCollection(join.apply(distinctDOY, ndviCol, filter));

// Calculate the absolute range, interquartile range, and median for the set
// of images composing each coincident doy observation group. The result is
// an image collection with an image representative per unique doy observation
// with bands that describe the 0, 25, 50, 75, 100 percentiles for the set of
// coincident doy images.
var comp = ee.ImageCollection(joinCol.map(function(img) {
  var doyCol = ee.ImageCollection.fromImages(img.get('doy_matches'));

  return doyCol
      .reduce(ee.Reducer.percentile(
          [0, 25, 50, 75, 100], ['p0', 'p25', 'p50', 'p75', 'p100']))
      .set({'doy': img.get('doy')});
}));

// Extract the inter-annual NDVI doy percentile statistics for the
// point of interest per unique doy representative. The result is
// is a feature collection where each feature is a doy representative that
// contains a property (row) describing the respective inter-annual NDVI
// variance, formatted as a list of values.
var reductionTable = comp.map(function(img) {
  var stats = ee.Dictionary(img.reduceRegion(
      {reducer: ee.Reducer.first(), geometry: geometry, scale: 250}));

  // Order the percentile reduction elements according to how you want columns
  // in the DataTable arranged (x-axis values need to be first).
  var row = ee.List([
    img.get('doy'),            // x-axis, day of year.
    stats.get(band + '_p50'),  // y-axis, median.
    stats.get(band + '_p0'),   // y-axis, min interval.
    stats.get(band + '_p25'),  // y-axis, 1st quartile interval.
    stats.get(band + '_p75'),  // y-axis, 3rd quartile interval.
    stats.get(band + '_p100')  // y-axis, max interval.
  ]);

  // Return the row as a property of an ee.Feature.
  return ee.Feature(null, {row: row});
});

// Aggregate the 'row' properties to make a server-side 2-D array (DataTable).
var dataTableServer = reductionTable.aggregate_array('row');

// Define column names and properties for the DataTable. The order should
// correspond to the order in the construction of the 'row' property above.
var columnHeader = ee.List([[
  {label: 'Day of year', role: 'domain'},
  {label: 'Median', role: 'data'},
  {label: 'p0', role: 'interval'},
  {label: 'p25', role: 'interval'},
  {label: 'p75', role: 'interval'},
  {label: 'p100', role: 'interval'}
]]);

// Concatenate the column header to the table.
dataTableServer = columnHeader.cat(dataTableServer);

// Use 'evaluate' to transfer the server-side table to the client, define the
// chart and print it to the console.
dataTableServer.evaluate(function(dataTableClient) {
  var chart = ui.Chart(dataTableClient).setChartType('LineChart').setOptions({
    title: 'Annual NDVI Time Series with Inter-Annual Variance',
    intervals: {style: 'area'},
    hAxis: {
      title: 'Day of year',
      titleTextStyle: {italic: false, bold: true},
    },
    vAxis: {title: 'NDVI (x1e4)', titleTextStyle: {italic: false, bold: true}},
    colors: ['0f8755'],
    legend: {position: 'none'}
  });
  print(chart);
});

간격을 나타내는 방법에는 여러 가지가 있습니다. 다음 예에서는 각 박스 스타일을 사용하여 intervals.style 속성을 'boxes'로 변경하여 밴드 대신 박스를 사용합니다.

dataTableServer.evaluate(function(dataTableClient) {
  var chart = ui.Chart(dataTableClient).setChartType('LineChart').setOptions({
    title: 'Annual NDVI Time Series with Inter-Annual Variance',
    intervals: {style: 'boxes', barWidth: 1, boxWidth: 1, lineWidth: 0},
    hAxis: {
      title: 'Day of year',
      titleTextStyle: {italic: false, bold: true},
    },
    vAxis: {title: 'NDVI (x1e4)', titleTextStyle: {italic: false, bold: true}},
    colors: ['0f8755'],
    legend: {position: 'none'}
  });
  print(chart);
});