ui.Chart
函式會從用戶端 JSON 物件算繪圖表,該物件遵循與 Google 圖表 DataTable
類別相同的結構,但缺少 DataTable
方法和可變動性。它基本上是一個 2D 表格,其中列代表觀測資料,欄代表觀測屬性。提供彈性的基礎介面,可在 Earth Engine 中繪製圖表。當您需要高度自訂圖表時,這會是個不錯的選擇。
DataTable
個結構定義
在 Earth Engine 中定義偽 DataTable
有兩種方式:JavaScript 2D 陣列和 JavaScript 文字物件。對於大多數應用程式來說,建立 2D 陣列是最簡單的方法。無論是哪種情況,傳遞至 ui.Chart
的表格都必須是用戶端物件。手動編碼的資料表本質上是用於用戶端,而計算物件則需要使用 evaluate
轉移至用戶端。如要進一步瞭解伺服器端和用戶端物件的差異,請參閱「用戶端與伺服器」一文。
JavaScript 陣列
二維 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
圖表
您可以透過 evaluate
從伺服器傳遞至用戶端的 2D ee.List
建立 DataTable
陣列。常見的情況是將 ee.FeatureCollection
、ee.ImageCollection
或這些元素的逐元素縮減轉換為 DataTable
。以下範例中採用的策略會將函式對應至 ee.ImageCollection
,以便縮減指定元素、從縮減結果組合 ee.List
,並將清單附加至傳回元素,做為名為 'row'
的屬性。新集合的每個元素都有一個 1D ee.List
,代表 DataTable
中的資料列。aggregate_array()
函式可用於將所有 'row'
屬性匯總至父項 ee.List
,以便在 DataTable
所需的形狀中建立 2D 伺服器端 ee.List
。自訂欄標題會連結至資料表,結果會透過 evaluate
傳輸至用戶端,並使用 ui.Chart
函式進行轉譯。
按區域劃分的時間序列
這個範例顯示森林生態區的 MODIS 衍生 NDVI 和 EVI 植被指數時間序列。系列中的每張圖片都會根據生態區域進行縮減,其結果會組合為 'row'
屬性,並匯總為 DataTable
,以便傳遞給用戶端並透過 ui.Chart
繪製圖表。請注意,這個程式碼片段會產生與 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); });