Gráficos da DataTable

A função ui.Chart renderiza gráficos de um objeto JSON do lado do cliente que segue a mesma estrutura da classe DataTable do Google Charts, mas não tem métodos DataTable nem mutabilidade. É basicamente uma tabela 2D com linhas que representam observações e colunas que representam atributos de observação. Ele oferece uma interface flexível e básica para a criação de gráficos no Earth Engine. É uma boa opção quando um alto grau de personalização de gráficos é necessário.

DataTable esquema

Há duas maneiras de definir um pseudo-DataTable no Earth Engine: uma matriz 2D do JavaScript e um objeto literal do JavaScript. Para a maioria dos aplicativos, a criação de uma matriz 2D é a abordagem mais simples. Em ambos os casos, a tabela transmitida para ui.Chart precisa ser um objeto do lado do cliente. Uma tabela codificada manualmente será inherentemente do lado do cliente, enquanto um objeto computado precisará ser transferido do lado do cliente usando evaluate. Consulte a página Cliente x servidor para mais informações sobre a distinção entre objetos do lado do servidor e do cliente.

Matriz JavaScript

Um DataTable 2D é composto por uma matriz de linhas e colunas. As linhas são observações e as colunas são atributos. A primeira coluna define valores para o eixo x, enquanto as outras definem valores para as séries do eixo y. A primeira linha deve ser um cabeçalho de coluna. O cabeçalho mais simples é uma série de rótulos de coluna, demonstrados no seguinte array DataTable que relaciona a população por estados selecionados.

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

Opcionalmente, as colunas podem ser designadas para uma função diferente da definição do domínio (eixo x) e dos dados (série do eixo y), por exemplo, anotação, intervalos, dicas de ferramentas ou estilo. No exemplo abaixo, a matriz de cabeçalho é apresentada como uma série de objetos, em que o papel de cada coluna é definido explicitamente. Os papéis de coluna aceitáveis para cada tipo de gráfico do Google podem ser encontrados na respectiva documentação, por exemplo, Formato de dados de gráfico de coluna.

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

As propriedades da coluna são especificadas da seguinte maneira:

Parâmetro Tipo Definição
type string, recomendado Tipo de dados da coluna: 'string', 'number', 'boolean', 'date', 'datetime' ou 'timeofday'.
label string, recomendado Um rótulo para a coluna, rótulo da série na legenda do gráfico.
role string, recomendado Uma função para a coluna (por exemplo, funções para o gráfico de colunas).
pattern string, opcional Uma string de formato de número (ou data) que especifica como exibir o valor da coluna.

Objeto JavaScript

Um DataTable pode ser formatado como um objeto literal do JavaScript em que matrizes de objetos de linha e coluna são fornecidas. Consulte este guia para instruções sobre como especificar parâmetros de coluna e linha.

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

Gráfico manual de DataTable

Suponha que você tenha uma pequena quantidade de dados estáticos que quer mostrar em um gráfico. Use as especificações de matriz ou objeto do JavaScript para criar uma entrada a ser transmitida à função ui.Chart. Aqui, as populações de estados selecionadas do censo dos EUA de 2010 são codificadas como uma matriz JavaScript com objetos de cabeçalho de coluna que definem as propriedades da coluna. A terceira coluna é designada para a função de 'annotation', que adiciona a população como uma anotação a cada observação no gráfico.

Editor de código (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);

Gráfico DataTable computado

Uma matriz DataTable pode ser criada a partir de um ee.List 2D transmitido do servidor para o cliente por evaluate. Um cenário comum é converter as propriedades de um ee.FeatureCollection, ee.ImageCollection ou redução elementar deles em um DataTable. A estratégia aplicada nos exemplos a seguir mapeia uma função em um ee.ImageCollection que reduz o elemento fornecido, monta um ee.List com os resultados da redução e anexa a lista como uma propriedade chamada 'row' ao elemento retornado. Cada elemento da nova coleção tem uma ee.List de 1D que representa uma linha em um DataTable. A função aggregate_array() é usada para agregar todas as propriedades 'row' em um ee.List pai para criar um ee.List bidimensional do lado do servidor na forma necessária para DataTable. Um cabeçalho de coluna personalizado é concatenado à tabela, e o resultado é transferido do lado do cliente com evaluate, onde é renderizado usando a função ui.Chart.

Séries temporais por região

Este exemplo mostra uma série temporal de índices de vegetação NDVI e EVI derivados do MODIS para uma ecoregião florestal. Cada imagem da série é reduzida pela ecorregião e os resultados são montados como uma propriedade 'row' que é agregada em um DataTable para transmissão ao cliente e criação de gráficos com ui.Chart. Esse snippet produz o mesmo gráfico gerado pelo exemplo de gráfico ui.Chart.image.series.

Editor de código (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);
});

Gráfico de intervalo

Esse gráfico aproveita a propriedade 'role' da coluna DataTable para gerar um gráfico de intervalos. O gráfico relaciona o perfil anual de NDVI e a variação interanual de um pixel perto de Monterey, CA. A mediana interanual é apresentada como uma linha, enquanto os intervalos absolutos e interquartílicos são mostrados como faixas. As colunas da tabela que representam cada intervalo são atribuídas dessa forma definindo a propriedade da coluna 'role' como 'interval'. As faixas são desenhadas ao redor da linha média definindo a propriedade do gráfico intervals.style como 'area'.

Editor de código (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);
});

Há muitas maneiras de representar intervalos. No exemplo a seguir, as caixas são usadas em vez de bandas, mudando a propriedade intervals.style para 'boxes' com o estilo de caixa correspondente.

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