DOI: 10.7910/dvn/m4zgxp
title: MSZSI: Multi-Scale Zonal Statistics [AgriClimate] Inventory

description: &lt;b&gt;MSZSI: Multi-Scale Zonal Statistics [AgriClimate] Inventory&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
--------------------------------------------------------------------------------------
&lt;br&gt;
MSZSI is a data extraction tool for Google Earth Engine that aggregates time-series remote sensing information to multiple administrative levels using the FAO GAUL data layers. The code at the bottom of this page (metadata) can be pasted into the Google Earth Engine JavaScript code editor and ran at https://code.earthengine.google.com/. 
&lt;br&gt;&lt;br&gt;
&lt;i&gt;Please refer to the associated publication&lt;/i&gt;: 
&lt;br&gt;
Peter, B.G., Messina, J.P., Breeze, V., Fung, C.Y., Kapoor, A. and Fan, P., 2024. Perspectives on modifiable spatiotemporal unit problems in remote sensing of agriculture: evaluating rice production in Vietnam and tools for analysis. &lt;i&gt;Frontiers in Remote Sensing&lt;/i&gt;, 5, p.1042624.
&lt;br&gt;
&lt;a href="https://www.frontiersin.org/journals/remote-sensing/articles/10.3389/frsen.2024.1042624"&gt;https://www.frontiersin.org/journals/remote-sensing/articles/10.3389/frsen.2024.1042624&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;i&gt;Input options:&lt;/i&gt;
&lt;br&gt;
[1] Country of interest
&lt;br&gt;
[2] Start and end year
&lt;br&gt;
[3] Start and end month
&lt;br&gt;
[4] Option to mask data to a specific land-use/land-cover type
&lt;br&gt;
[5] Land-use/land-cover type code from CGLS LULC
&lt;br&gt;
[6] Image collection for data aggregation
&lt;br&gt;
[7] Desired band from the image collection
&lt;br&gt;
[8] Statistics type for the zonal aggregations
&lt;br&gt;
[9] Statistic to use for annual aggregation
&lt;br&gt;
[10] Scaling options
&lt;br&gt;
[11] Export folder and label suffix
&lt;br&gt;&lt;br&gt;
&lt;i&gt;Output:&lt;/i&gt; Two CSVs containing zonal statistics for each of the FAO GAUL administrative level boundaries
&lt;br&gt;
&lt;i&gt;Output fields:&lt;/i&gt; system:index, 0-ADM0_CODE, 0-ADM0_NAME, 0-ADM1_CODE, 0-ADM1_NAME, 0-ADMN_CODE, 0-ADMN_NAME, 1-AREA_PERCENT_LULC, 1-AREA_SQM_LULC, 1-AREA_SQM_ZONE, 2-X_2001, 2-X_2002, 2-X_2003, ..., 2-X_2020, .geo
&lt;br&gt;&lt;br&gt;
&lt;img src ="https://github.com/cartoscience/seagul/blob/main/mszsi/mszsi_input_v5.PNG?raw=true" width="1000" height="auto"&lt;/img&gt;
&lt;br&gt;&lt;br&gt;
&lt;b&gt;PREPROCESSED DATA DOWNLOAD&lt;/b&gt;
&lt;br&gt;&lt;br&gt;
The datasets available for download contain zonal statistics at 2 administrative levels (FAO GAUL levels 1 and 2). Select countries from Southeast Asia and Sub-Saharan Africa &lt;b&gt;(Cambodia, Indonesia, Lao PDR, Myanmar, Philippines, Thailand, Vietnam, Burundi, Kenya, Malawi, Mozambique, Rwanda, Tanzania, Uganda, Zambia, Zimbabwe)&lt;/b&gt; are included in the current version, with plans to extend the dataset to contain global metrics. Each zip file is described below and two example NDVI tables are available for preview.
&lt;br&gt;&lt;br&gt;
&lt;b&gt;Key&lt;/b&gt;: [source, data, units, temporal range, aggregation, masking, zonal statistic, notes] 
&lt;br&gt;&lt;br&gt;
Currently available:
&lt;br&gt;&lt;b&gt;MSZSI-V2_V-NDVI-MEAN.tar&lt;/b&gt;: [NASA-MODIS, NDVI, index, 2001–2020, annual mean, agriculture, mean, n/a] 
&lt;br&gt;&lt;b&gt;MSZSI-V2_T-LST-DAY-MEAN.tar&lt;/b&gt;: [NASA-MODIS, LST Day, °C, 2001–2020, annual mean, agriculture, mean, n/a] 
&lt;br&gt;&lt;b&gt;MSZSI-V2_T-LST-NIGHT-MEAN.tar&lt;/b&gt;: [NASA-MODIS, LST Night, °C, 2001–2020, annual mean, agriculture, mean, n/a] 
&lt;br&gt;&lt;b&gt;MSZSI-V2_R-PRECIP-SUM.tar&lt;/b&gt;: [UCSB-CHG-CHIRPS, Precipitation, mm, 2001–2020, annual sum, agriculture, mean, n/a] 
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-BDENS-MEAN.tar&lt;/b&gt;: [OpenLandMap, Bulk density, g/cm3, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-ORGC-MEAN.tar&lt;/b&gt;: [OpenLandMap, Organic carbon, g/kg, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-PH-MEAN.tar&lt;/b&gt;: [OpenLandMap, pH in H2O, pH, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-WATER-MEAN.tar&lt;/b&gt;: [OpenLandMap, Soil water, % at 33kPa, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-SAND-MEAN.tar&lt;/b&gt;: [OpenLandMap, Sand, %, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-SILT-MEAN.tar&lt;/b&gt;: [OpenLandMap, Silt, %, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_S-CLAY-MEAN.tar&lt;/b&gt;: [OpenLandMap, Clay, %, static, n/a, agriculture, mean, at depths 0-10-30-60-100-200]
&lt;br&gt;&lt;b&gt;MSZSI-V2_E-ELEV-MEAN.tar&lt;/b&gt;: [MERIT, [elevation, slope, flowacc, HAND], [m, degrees, km&lt;sup&gt;2&lt;/sup&gt;, m], static, n/a, agriculture, mean, n/a]
&lt;br&gt;&lt;br&gt;&lt;i&gt;Coming soon&lt;/i&gt;
&lt;br&gt;&lt;b&gt;MSZSI-V2_C-STAX-MEAN.tar&lt;/b&gt;: [OpenLandMap, Soil taxonomy, category, static, n/a, agriculture, area sum, n/a]
&lt;br&gt;&lt;b&gt;MSZSI-V2_C-LULC-MEAN.tar&lt;/b&gt;: [CGLS-LC100-V3, LULC, category, 2015–2019, mode, none, area sum, n/a]
&lt;br&gt;&lt;br&gt;&lt;br&gt;
&lt;img src ="https://github.com/cartoscience/seagul/blob/main/mszsi/mszsi_diagram_v2.png?raw=true" width="1000" height="auto"&lt;/img&gt;
&lt;br&gt;&lt;br&gt;
&lt;b&gt;Data sources:&lt;/b&gt; 
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/MODIS_006_MOD13Q1"&gt;https://developers.google.com/earth-engine/datasets/catalog/MODIS_006_MOD13Q1&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/MODIS_006_MOD11A2"&gt;https://developers.google.com/earth-engine/datasets/catalog/MODIS_006_MOD11A2&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/UCSB-CHG_CHIRPS_PENTAD"&gt;https://developers.google.com/earth-engine/datasets/catalog/UCSB-CHG_CHIRPS_PENTAD&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_BULKDENS-FINEEARTH_USDA-4A1H_M_v02"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_BULKDENS-FINEEARTH_USDA-4A1H_M_v02&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_ORGANIC-CARBON_USDA-6A1C_M_v02"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_ORGANIC-CARBON_USDA-6A1C_M_v02&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_PH-H2O_USDA-4C1A2A_M_v02"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_PH-H2O_USDA-4C1A2A_M_v02&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_WATERCONTENT-33KPA_USDA-4B1C_M_v01"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_WATERCONTENT-33KPA_USDA-4B1C_M_v01&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_CLAY-WFRACTION_USDA-3A1A1A_M_v02"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_CLAY-WFRACTION_USDA-3A1A1A_M_v02&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_SAND-WFRACTION_USDA-3A1A1A_M_v02"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_SAND-WFRACTION_USDA-3A1A1A_M_v02&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_GRTGROUP_USDA-SOILTAX_C_v01"&gt;https://developers.google.com/earth-engine/datasets/catalog/OpenLandMap_SOL_SOL_GRTGROUP_USDA-SOILTAX_C_v01&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_Landcover_100m_Proba-V-C3_Global"&gt;https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_Landcover_100m_Proba-V-C3_Global&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/MERIT_Hydro_v1_0_1"&gt;https://developers.google.com/earth-engine/datasets/catalog/MERIT_Hydro_v1_0_1&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level0"&gt;https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level0&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level1"&gt;https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level1&lt;/a&gt;
&lt;br&gt;&lt;li&gt;&lt;a href="https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level2"&gt;https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level2&lt;/a&gt;&lt;/li&gt;
&lt;br&gt;
&lt;b&gt;Project information:&lt;/b&gt;
&lt;br&gt;
SEAGUL: Southeast Asia Globalization, Urbanization, Land and Environment Changes
&lt;br&gt;
&lt;a href="http://seagul.info/"&gt;http://seagul.info/&lt;/a&gt;; &lt;a href="https://lcluc.umd.edu/projects/divergent-local-responses-globalization-urbanization-land-transition-and-environmental"&gt;https://lcluc.umd.edu/projects/divergent-local-responses-globalization-urbanization-land-transition-and-environmental&lt;/a&gt;
&lt;br&gt;
This project was made possible by the the NASA Land-Cover/Land-Use Change Program (Grant #: 80NSSC20K0740)
&lt;br&gt;&lt;br&gt;
For an additional interactive visualization, visit: &lt;a href="https://cartoscience.users.earthengine.app/view/maup-mapper-multi-scale-modis-ndvi"&gt;https://cartoscience.users.earthengine.app/view/maup-mapper-multi-scale-modis-ndvi&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;img src ="https://github.com/cartoscience/seagul/blob/main/mszsi/mszsi_app.png?raw=true" width="1000" height="auto"&lt;/img&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
&lt;i&gt; Google Earth Engine code&lt;/i&gt;
&lt;pre&gt;
/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MSZSI: Multi-Scale Zonal Statistics Inventory
Authors: Brad G. Peter, Department of Geography, University of Alabama
 Joseph Messina, Department of Geography, University of Alabama
 Austin Raney, Department of Geography, University of Alabama
 Rodrigo E. Principe, AgriCircle AG
 Peilei Fan, Department of Geography, Environment, and Spatial Sciences, Michigan State University

Citation:
Peter, Brad; Messina, Joseph; Raney, Austin; Principe, Rodrigo; Fan, Peilei, 2021, 
"MSZSI: Multi-Scale Zonal Statistics Inventory", https://doi.org/10.7910/DVN/YCUBXS, Harvard Dataverse, V#

SEAGUL: Southeast Asia Globalization, Urbanization, Land and Environment Changes
http://seagul.info/
https://lcluc.umd.edu/projects/divergent-local-responses-globalization-urbanization-land-transition-and-environmental
This project was made possible by the the NASA Land-Cover/Land-Use Change Program (Grant #: 80NSSC20K0740)
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/

/*-----------------------------------------------------------------------------------------------------------------------------------
Description: MSZSI is a data extraction tool for aggregating time-series remote sensing information to multiple administrative levels 
using the FAO GAUL data layers.

Input parameterization:
[1] Enter the country code for the desired country
[2] Select a start and end year. Be sure to check for data availability in the collection selected in input 6.
[3] Select a start month and end month to specify a temporal range within each year. 
[4] Select an image collection for data aggregation.
[5] Select the desired band from the image collection.
[6] Option to mask data to a specific land-use/land-cover type. Enter 'TRUE' or 'FALSE'.
[7] Enter a land-use/land-cover type code from CGLS LULC. Ignore this option if no masking is desired and set input 4 to 'FALSE'.
[8] Select a statistics type for the zonal aggregations (defaults to mean)
[9] Select a statistic for temporal aggregation (see available options in the parameterization below)
[10] Scaling options
[11] Export folder output file label suffix

Check tasks tab for CSV exports. Select a point on the map to view timeseries statistics. 
Hover over the layers panel to turn layers on/off and set visualization parameters. 

For an additional interactive visualization, visit: https://cartoscience.users.earthengine.app/view/maup-mapper-multi-scale-modis-ndvi

Boundary data Layers:
https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level0
https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level1
https://developers.google.com/earth-engine/datasets/catalog/FAO_GAUL_2015_level2
-----------------------------------------------------------------------------------------------------------------------------------*/

// ••••••••••••••••••••••••••••••••••••••••••••••••••••• USER PARAMETERIZATION ••••••••••••••••••••••••••••••••••••••••••••••••••••••

/*[1]*/ var countryCode = 264
 // Refer to http://www.fao.org/in-action/countrystat/news-and-events/events/training-material/gaul-codes2014/en/

/*[2]*/ var startYear = 2001 // Check data availability for the collection selected in input 4
 var endYear = 2020
/*[3]*/ var startMonth = 1
 var endMonth = 12

/*[4]*/ var ic = ee.ImageCollection('MODIS/006/MOD13Q1')
/*[5]*/ var band = 'NDVI'

/*[6]*/ var maskToLULC = 'TRUE' // Set to 'TRUE' or 'FALSE' 
/*[7]*/ var lcType = 40 
 // Refer to https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_Landcover_100m_Proba-V-C3_Global

/*[8]*/ var zonalStatType = ee.Reducer.mean() // examples: ee.Reducer.mean(), ee.Reducer.median(), ee.Reducer.stdDev(), 
 // ee.Reducer.min(), ee.Reducer.max(), ee.Reducer.sum()
/*[9]*/ var temporalAggregateType = 'mean' // available options: 'mean', 'median', 'stddev', 'min', 'max', 'sum'

/*[10]*/ var nativeScale = 'TRUE' // Set to 'TRUE' or 'FALSE'
 var scale = 1000 // option to increase the scale to avoid memory crashes

/*[11]*/ var exportFolder = 'GEE_Exports'
 var labelSuffix = 'NDVI-MEAN_VIETNAM'
 // sample export name: MSZSI-V2_2001-2020_1-12_LC40_GAUL-152-L1_NDVI-MEAN_VIETNAM, but can be changed during download prompt
 // note that some country names will need to be adjusted in the download prompt if they contain special characters

///////////////////////////////////////////////////// NO USER INPUT NEEDED BELOW ////////////////////////////////////////////////////

// Administrative zones and preprocessing -------------------------------------------------------------------------------------------
ic = ic.select(band)
var years = ee.List.sequence(startYear,endYear)

var fc_L0 = ee.FeatureCollection('FAO/GAUL/2015/level0').filterMetadata('ADM0_CODE','equals',countryCode)
var fc_L1 = ee.FeatureCollection('FAO/GAUL/2015/level1').filterMetadata('ADM0_CODE','equals',countryCode)
 .select(['ADM0_CODE','ADM0_NAME','ADM1_CODE','ADM1_NAME'],
 ['0-ADM0_CODE','0-ADM0_NAME','0-ADM1_CODE','0-ADM1_NAME'])
fc_L1 = fc_L1.map(function(f) {
 return f.set('0-ADM2_CODE','NULL').set('0-ADM2_NAME','NULL')
 })
 
var fc_L2 = ee.FeatureCollection('FAO/GAUL/2015/level2').filterMetadata('ADM0_CODE','equals',countryCode)
 .select(['ADM0_CODE','ADM0_NAME','ADM1_CODE','ADM1_NAME','ADM2_CODE','ADM2_NAME'],
 ['0-ADM0_CODE','0-ADM0_NAME','0-ADM1_CODE','0-ADM1_NAME','0-ADM2_CODE','0-ADM2_NAME'])

// LULC preprocessing ---------------------------------------------------------------------------------------------------------------
var lulc = ee.ImageCollection('COPERNICUS/Landcover/100m/Proba-V-C3/Global').select('discrete_classification')
var lulcMode = lulc.mode().eq(lcType)
var lcLabel = '_LC'+lcType
var lulcClip = lulcMode.clip(fc_L0)
var lulcZone = lulcClip.remap([0,1],[1,1]).rename('zoneArea')
var mask = lulcClip.updateMask(lulcClip.eq(1)).rename('mask')

if(maskToLULC == 'FALSE') {
 lcLabel = ''
 mask = lulcZone
}

if(nativeScale == 'TRUE') {
 scale = lulc.first().projection().nominalScale()
}

// Add area fields ------------------------------------------------------------------------------------------------------------------
var temporal = ee.ImageCollection(years.map(function(y) {
 var filterYear = ic.filter(ee.Filter.calendarRange(y,y,'year'))
 .filter(ee.Filter.calendarRange(startMonth, endMonth, 'month'))

 var aggregate // the temporal aggregation type is set in input 9
 if (temporalAggregateType == 'mean') {
 aggregate = filterYear.mean()
 }
 if (temporalAggregateType == 'median') {
 aggregate = filterYear.median()
 }
 if (temporalAggregateType == 'stddev') {
 aggregate = filterYear.stdDev()
 }
 if (temporalAggregateType == 'min') {
 aggregate = filterYear.min()
 }
 if (temporalAggregateType == 'max') {
 aggregate = filterYear.max()
 }
 if (temporalAggregateType == 'sum') {
 aggregate = filterYear.sum()
 }
 
 return aggregate.where(aggregate.eq(0),1e-10) // True zeroes are currently set to 1e-10 to avoid false no data flags
 .updateMask(mask)
 .set('extract',ee.String('2-'+labelSuffix+'_').cat(ee.Number(y).toInt()))
 .set('year',ee.Number(y).toInt())
 .rename('band')
}))

// Run functions for each administrative level --------------------------------------------------------------------------------------
var zonal_L1 = zonalStat(fc_L1)
var zonal_L2 = zonalStat(fc_L2)
var merge = zonal_L1.combine(zonal_L2)

var fcAreas_L1 = getAreas(fc_L1)
var fcAreas_L2 = getAreas(fc_L2)

var samples_L1 = createSamples(fc_L1)
var samples_L2 = createSamples(fc_L2)

var added_L1 = addFields(samples_L1,fcAreas_L1.select('zoneAreas'),fcAreas_L1.select('lulcAreas'))
var added_L2 = addFields(samples_L2,fcAreas_L2.select('zoneAreas'),fcAreas_L2.select('lulcAreas'))

exporter(added_L1,zonal_L1,1)
exporter(added_L2,zonal_L2,2)

// Calculate zonal statistics -------------------------------------------------------------------------------------------------------
function zonalStat(fc) {
 return temporal.map(function(i) {
 var year = i.get('year')
 return i.reduceRegions({
 collection: fc,
 reducer: ee.Reducer.mean().setOutputs(['zStat']), 
 scale: scale
 }).reduceToImage({
 properties: ['zStat'],
 reducer: ee.Reducer.first()
 }).set('extract',i.get('extract')).set('year',year).rename('band')
 })
}

// Calculate areas ------------------------------------------------------------------------------------------------------------------
function getAreas(fc) {
 var zoneAreas = ee.Image.pixelArea().updateMask(lulcZone).reduceRegions({
 collection: fc,
 reducer: ee.Reducer.sum(), 
 scale: scale
 }).reduceToImage({
 properties: ['sum'],
 reducer: ee.Reducer.first()
 }).rename('zoneAreas')
 var lulcAreas = ee.Image.pixelArea().updateMask(mask).reduceRegions({
 collection: fc,
 reducer: ee.Reducer.sum(), 
 scale: scale
 }).reduceToImage({
 properties: ['sum'],
 reducer: ee.Reducer.first()
 }).rename('lulcAreas')
 return zoneAreas.addBands(lulcAreas)
}

// Feature to points ----------------------------------------------------------------------------------------------------------------
function createSamples(fc) {
 return fc.map(function(g) {
 return ee.Feature(ee.FeatureCollection.randomPoints({
 region: g.geometry(), 
 points: 1, 
 seed: 0
 }).geometry()).copyProperties(g)
 }) 
}

// Add area fields ------------------------------------------------------------------------------------------------------------------
function addFields(samples, areaGridZone, areaGridLULC) {
 return samples.map(function(p) {
 var point = p.geometry()
 var zoneArea = areaGridZone.rename('area').reduceRegion({
 reducer: ee.Reducer.first(), 
 geometry: point, 
 scale: 1, 
 maxPixels: 1e13
 }).get('area')
 var lulcArea = areaGridLULC.rename('area').reduceRegion({
 reducer: ee.Reducer.first(),
 geometry: point,
 scale: 1
 }).get('area')
 var percLULC = ee.Number(lulcArea).divide(zoneArea).multiply(100)
 return ee.Feature(p).set('1-AREA_SQM_LULC',0)
 .set('1-AREA_SQM_ZONE',zoneArea).set('1-AREA_SQM_LULC',ee.Algorithms.If(lulcArea,lulcArea,0))
 .set('1-AREA_PERCENT_LULC',ee.Algorithms.If(lulcArea,percLULC,0))
 })
}

// Export function ------------------------------------------------------------------------------------------------------------------
function exporter(e,zones,n) {
 var extracted = e.map(extractToPoints)
 function extractToPoints(feature) {
 var geom = feature.geometry()
 var addField = function(image, f) {
 var newFeature = ee.Feature(f)
 var getName = image.get('extract')
 var setValue = image.reduceRegion({
 reducer: ee.Reducer.first(), 
 geometry: geom, 
 scale: 1, 
 maxPixels: 1e13
 }).get('band')
 return ee.Feature(ee.Algorithms.If(setValue,
 newFeature.set(getName, ee.String(setValue)),
 newFeature.set(getName, ee.String('No data'))))
 }
 var newFeature = ee.Feature(zones.iterate(addField, feature))
 return newFeature
 }
 
 Export.table.toDrive({
 collection: extracted,
 description: 'MSZSI-V2_'+startYear+'-'+endYear+'_'+startMonth+'-'+endMonth
 +lcLabel+'_GAUL-'+countryCode+'-L'+n+'_'+labelSuffix,
 folder: exportFolder
 })
}

// Map display settings -------------------------------------------------------------------------------------------------------------
var leftMap = ui.Map()
var rightMap = ui.Map()
ui.Map.Linker([leftMap, rightMap])
ui.root.widgets().reset([leftMap,rightMap])
leftMap.centerObject(fc_L0)
leftMap.setOptions('HYBRID').style().set('cursor', 'crosshair')
rightMap.setOptions('HYBRID').style().set('cursor', 'crosshair')

// Adds each image to the map displays
var len = years.length().getInfo()
for (var i = 0; i &lt; len; i++) {
 var year = i+startYear
 var namer = 'ZSTATS_'+year
 var image_L1 = ee.Image(zonal_L1.toList(zonal_L1.size()).get(i)).rename(band)
 var image_L2 = ee.Image(zonal_L2.toList(zonal_L2.size()).get(i)).rename(band)
 leftMap.addLayer(image_L1,{},namer,false)
 rightMap.addLayer(image_L2,{},namer,false)
}

var hollow = {color: 'white', width: 0.3, fillColor: '00000000'}
leftMap.addLayer(fc_L1.style(hollow),{},'FAO-GAUL-L1')
rightMap.addLayer(fc_L2.style(hollow),{},'FAO-GAUL-L2')

// Chart display settings -----------------------------------------------------------------------------------------------------------
var chartOptions = {
 fontSize: 11,
 width: '100px',
 curveType: 'function',
 format: 'short',
 margin: '0 0 0 0',
 hAxis: {format: '0000', textStyle: {fontSize: 10, color: '303030'}, gridlines: {color: 'transparent'}},
 vAxis: {textStyle: {fontSize: 10, color: '303030'}, gridlines: {}},
 trendlines: {0: {color: '303030', lineWidth: 0.5, visibleInLegend: false}},
 series: {0: {color: '303030', lineWidth: 0.8}},
 legend: {textStyle: {color: '303030'}},
}

var panelStyle = {
 width: '235px',
 position: 'bottom-left',
 margin: '0 0 0 0',
 border: '1px solid #303030'
}
var leftChart = ui.Panel({
 widgets: ui.Label('Select a point to chart regional time-series',{margin: '0 0 0 0', color:'303030'}),
 style: panelStyle
})
leftMap.add(leftChart)

// onClick function to query time-series -------------------------------------------------------------------------------------------- 
function pickLocation(location) {
 leftChart.widgets().set(0,ui.Label('Time-series',{fontSize: '14px', fontWeight: 'bold', color: '303030', margin: '7px 0 7px 10px'}))
 var chartOptions = {
 fontSize: 10,
 height: '200px',
 curveType: 'function',
 format: 'short',
 margin: '0 0 0 0',
 hAxis: {format: '0000', textStyle: {fontSize: 11, color: '303030'}, gridlines: {color: 'transparent'}},
 vAxis: {textStyle: {fontSize: 10, color: '303030'}, gridlines: {}},
 trendlines: {0: {color: 'blue', lineWidth: 0.5, visibleInLegend: false},
 1: {color: 'red', lineWidth: 0.5, visibleInLegend: false}
 },
 series: {0: {color: 'blue', lineWidth: 0.8},
 1: {color: 'red', lineWidth: 0.8}
 },
 legend: {position:'none'}
 }
 
 leftChart.widgets().set(1,ui.Label('Loading...',{fontSize: '13px',color:'9C9C9C', margin: '0 0 7px 10px'}))
 leftChart.widgets().set(2,ui.Label('',{fontSize: '13px',color:'9C9C9C', margin: '0 0 7px 10px'}))
 
 var pLat = location.lat
 var pLon = location.lon
 var point = ee.Geometry.Point([pLon,pLat])
 var selection_L1 = fc_L1.filterBounds(point)
 var selection_L2 = fc_L2.filterBounds(point)
 var zone_L1_name = ee.Feature(selection_L1.first()).get('0-ADM1_NAME')
 var zone_L2_name = ee.Feature(selection_L2.first()).get('0-ADM2_NAME')
 
 leftChart.widgets().set(3,ui.Chart.image.series({
 imageCollection: merge,
 region: point,
 scale: scale,
 xProperty: 'year'
 }).setOptions(chartOptions))
 
 zone_L1_name.evaluate(function(result_L1) {
 zone_L2_name.evaluate(function(result_L2) {
 leftChart.widgets().set(1,ui.Label(result_L1+' (L1)',{fontSize: '13px', color: 'blue', margin: '0 0 7px 10px'}))
 leftChart.widgets().set(2,ui.Label(result_L2+' (L2)',{fontSize: '13px', color: 'red', margin: '0 0 0 10px'}))
 })
 })
 
 leftMap.layers().set(len+1, ui.Map.Layer(point,{color: 'blue', opacity: 0.6},'Selected point'))
 rightMap.layers().set(len+1, ui.Map.Layer(point,{color: 'red', opacity: 0.6},'Selected point'))
}

leftMap.onClick(pickLocation)
rightMap.onClick(pickLocation)
&lt;/pre&gt;