Wykresy w tabeli danych

Funkcja ui.Chart renderuje wykresy z obiektu JSON po stronie klienta, który ma taką samą strukturę jak klasa DataTable w Google Charts, ale nie zawiera metod DataTable ani możliwości zmiany. Jest to w podstawie tabela dwuwymiarowa z wierszami reprezentującymi obserwacje i kolumnami reprezentującymi atrybuty obserwacji. Udostępnia on elastyczny podstawowy interfejs do tworzenia wykresów w Earth Engine. Jest to dobra opcja, gdy wymagane jest dostosowanie wykresu.

DataTable schemat

W Earth Engine pseudo-DataTable można zdefiniować na 2 sposoby: za pomocą tablicy 2D w JavaScript i obiektu literackiego w JavaScript. W większości przypadków najprostszym sposobem jest utworzenie tablicy dwuwymiarowej. W obu przypadkach tabela przekazana do funkcji ui.Chart musi być obiektem po stronie klienta. Ręcznie zakodowana tabela będzie z założenia po stronie klienta, natomiast obiekt obliczony będzie musiał zostać przeniesiony po stronie klienta za pomocą elementu evaluate. Więcej informacji o różnicach między obiektami po stronie serwera a obiektami po stronie klienta znajdziesz na stronie Client vs. Server.

tablica w JavaScript,

Macierz dwuwymiarowa DataTable składa się z tablicy wierszy i kolumn. Wiersze to obserwacje, a kolumny to atrybuty. Pierwsza kolumna określa wartości osi X, a dodatkowe kolumny – wartości serii osi Y. Pierwszy wiersz powinien być nagłówkiem kolumny. Najprostszy nagłówek to seria etykiet kolumn, jak w tym tablicowym ciągu DataTable, który łączy ze sobą dane o liczebności populacji w wybranych stanach.

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

Opcjonalnie kolumny mogą pełnić inne role niż definiowanie domeny (osi X) i danych (serii osi Y), np. adnotacji, przedziałów, etykiet lub stylu. W tym przykładzie tablica nagłówków jest przedstawiona jako seria obiektów, w których wyraźnie określono rolę każdej kolumny. Akceptowane role kolumn dla każdego typu wykresu Google można znaleźć w odpowiedniej dokumentacji, np. Format danych wykresu kolumnowego.

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'],
];

Właściwości kolumny są określane w ten sposób:

Parametr Typ Definicja
type ciąg tekstowy (zalecane) Typ danych kolumny: 'string', 'number', 'boolean', 'date', 'datetime' lub 'timeofday'.
label ciąg tekstowy (zalecane) Etykieta kolumny, czyli etykieta serii w legendzie wykresu.
role ciąg tekstowy (zalecane) Rola kolumny (np. role for Column Chart).
pattern ciąg, opcjonalnie ciąg tekstowy formatu liczby (lub daty) określający sposób wyświetlania wartości kolumny;

Obiekt JavaScript

Wartość DataTable może być sformatowana jako obiekt dosłowny JavaScriptu, w którym podawane są tablice obiektów wiersza i kolumny. Więcej informacji o określaniu parametrów kolumn i wierszy znajdziesz w tym przewodniku.

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}]}]
};

Wykres ręczny DataTable

Załóżmy, że masz niewielką ilość danych statycznych, które chcesz wyświetlić na wykresie. Użyj specyfikacji tablicy lub obiektu w JavaScript, aby utworzyć dane wejściowe, które zostaną przekazane funkcji ui.Chart. Tutaj dane dotyczące liczby ludności w wybranych stanach z amerykańskiego spisu ludności z 2010 r. są zakodowane jako tablica JavaScriptu z obiektmi nagłówków kolumn, które definiują właściwości kolumn. Pamiętaj, że trzecia kolumna jest przeznaczona do roli 'annotation', która dodaje populację jako adnotację do każdego punktu na wykresie.

Edytor kodu (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);

Wynikowy wykres DataTable

Tablicę DataTable można utworzyć na podstawie dwuwymiarowej tablicy ee.List przekazanej z serwera do klienta za pomocą evaluate. Typowym scenariuszem jest konwertowanie właściwości obiektu ee.FeatureCollection lub ee.ImageCollection albo ich redukcja do postaci DataTable. Strategia zastosowana w tych przykładach mapuje funkcję na ee.ImageCollection, która redukuje dany element, składa ee.List z wyników redukcji i dołącza listę jako właściwość o nazwie 'row' do zwróconego elementu. Każdy element nowej kolekcji ma jednowymiarową tablicę ee.List, która reprezentuje wiersz w tablicy DataTable. Funkcja aggregate_array() służy do agregacji wszystkich właściwości 'row' w nadrzędnym obiekcie ee.List, aby utworzyć dwuwymiarowy obiekt ee.List po stronie serwera w kształcie wymaganym przez funkcję DataTable. Do tabeli dołączana jest nagłówek kolumny niestandardowej, a jej wynik jest przekazywany po stronie klienta za pomocą funkcji evaluate, gdzie jest renderowany za pomocą funkcji ui.Chart.

Ciągi czasowe według regionu

Ten przykład pokazuje czasową sekwencję indeksów wegetacji NDVI i EVI uzyskanych na podstawie danych MODIS w ekoregionie porostów leśnych. Każde obraz w serii jest zmniejszane według ekoregionu, a jego wyniki są łączone jako właściwości 'row', które są agregowane w element DataTable, aby przekazać go do klienta i wykorzystać na wykresie za pomocą funkcji ui.Chart. Ten fragment kodu generuje ten sam wykres, co przykładowy wykres ui.Chart.image.series.

Edytor kodu (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);
});

Wykres przedziałowy

Ten wykres korzysta z właściwości kolumny DataTable 'role' do generowania wykresu przedziałowego. Wykres przedstawia związek między rocznym profilem NDVI a rocznymi odstępstwami w przypadku piksela w pobliżu Monterey w Kalifornii. Mediana międzyroczna jest przedstawiona jako linia, a zakresy bezwzględne i interkwartylowe – jako pasy. Kolumny tabeli reprezentujące poszczególne przedziały są przypisywane jako takie przez ustawienie właściwości kolumny 'role' na 'interval'. Pasy są narysowane wokół linii mediany przez ustawienie właściwości wykresu intervals.style na 'area'.

Edytor kodu (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);
});

Intervaly można przedstawiać na wiele sposobów. W tym przykładzie zamiast pasm użyto pudełek, zmieniając właściwość intervals.style na 'boxes' z odpowiednim formatowaniem pudełka.

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);
});