1

I'm using Chart.image.series() in Google Earth Engine to create a line chart with two series from an image collection of processed land cover data (two binary bands per year: grass/shrub/wetland, and cropland/developed) and a region (10 mi radius circle).

I would like the y-axis values (sum area) to be log transformed but I can't figure out how to do that. Such as if ee.Reducer.sum().log() was allowed.

https://code.earthengine.google.com/c08b3d0316375648af0fe1cd4fe8128a

//try to calculate landcover rate of change for cropland/developed and grass/shrub/wetlands


//Get CDL, and point of interest
var imageCollection = ee.ImageCollection("USDA/NASS/CDL")
var geometry = /* color: #d63000 */ee.Geometry.Point([-100.12247612030984, 46.13719639996092]);
var mi10 = geometry.buffer(16093.4);

Map.centerObject(mi10, 10);

var ic= imageCollection.filterDate('2008', '2019');
//print(ic);

//get grass, shrub, wetlands
//other hay non-alfalfa 37, shrubland 64, 152, wetlands 87,  190, 195, grass 176 
//get crop and development
// crop 1-36, 38-61, 66-77, 82, 204-254, devleoped 121-124
var gogetit = function(image){
  var cropland = image.select('cropland');
  
  var total = cropland.eq(37).or(cropland.eq(64)).or(cropland.eq(152))
  .or(cropland.eq(87)).or(cropland.eq(195)).or(cropland.eq(190)).or(cropland.eq(176));
  
  var cropdev = cropland.gte(1).and(cropland.lte(36))
  .or(cropland.gte(38).and(cropland.lte(61)))
  .or(cropland.gte(66).and(cropland.lte(77))).or(cropland.eq(82))
  .or(cropland.gte(121).and(cropland.lte(124)))
  .or(cropland.gte(204).and(cropland.lte(254)));
  
  var total_fm = total.focal_mode(75, 'square', 'meters');
  var cropdev_fm = cropdev.focal_mode(75, 'square', 'meters');
  
  return total_fm.addBands(cropdev_fm).rename(['grass/shrub/wetland', 'crop/developed'])
  .set('system:time_start', image.get('system:time_start'));
};
var ic2 = ic.map(gogetit);
print(ic2)

var crop08 = ic2.first().select('crop/developed');
var grass18 = ee.Image(ic2.filterMetadata('system:index', 'equals', '2018').first());
var grass18 = grass18.select('grass/shrub/wetland');
var grass08 = ic2.first().select('grass/shrub/wetland');
Map.addLayer(crop08.updateMask(crop08),{palette:['yellow']}, 'crop08')
Map.addLayer(grass08.updateMask(grass08),{palette:['red']}, 'grass08')
Map.addLayer(grass18.updateMask(grass18),{palette:['green']}, 'grass18')
Map.addLayer(mi10, {}, 'area');

//convert to area
var prep = function(image){
return image.multiply(ee.Image.pixelArea()).set('system:time_start', image.get('system:time_start'));
};
var ic2 = ic2.map(prep);
//print(ic2);

//line chart for two landcovers with trendlines
var chartit = new ui.Chart.image.series(ic2, mi10, ee.Reducer.sum(), 30)
.setOptions({
      title: 'Grass/Shrub/Wetland vs. Crop/Developed',
      hAxis: {'title': 'Year'},
      vAxis: {'title': 'Area'},
      trendlines: { 0: {showR2: true, visibleInLegend: true} , 
                    1: {showR2: true, visibleInLegend: true}}
                    });
print(chartit);

1 Answer 1

2

You can perform the reduceRegion outside of the chart reduction, which allows you to log transform the values. Set the log values as properties of the images and then you can chart them using the ui.Chart.feature.byFeature function. Here is the code you need to add to your script:

// Define a function to perform log transformation of region reduction results.
function logTransformation(img){
  // Reduce region (sum).
  var imgDict = img.reduceRegion({
    reducer: ee.Reducer.sum(),
    geometry: mi10,
    scale: 30
  });

  // Get the bands and values from the reduce region dictionary.
  var keys = imgDict.keys();
  var vals = imgDict.values();

  // Map over the values and transform to log.
  var valsLog = vals.map(function(val){
    return ee.Number(val).log();
  });

  // Make a dictionary from the band anmes and new log values.
  var imgDictLog = ee.Dictionary.fromLists(keys, valsLog);

  // Return image with properties set from the band names and log transformations.
  return img.set(imgDictLog);
}

// Apply region reduction and log transformation.
var ic2Reduced = ic2.map(logTransformation);

// Line chart for two landcovers with trendlines
var chartLog = ui.Chart.feature.byFeature(
  ic2Reduced,
  'system:time_start',
  ['crop/developed', 'grass/shrub/wetland']
)
.setOptions({
      title: 'Grass/Shrub/Wetland vs. Crop/Developed',
      hAxis: {'title': 'Year'},
      vAxis: {'title': 'Area'},
      trendlines: { 0: {showR2: true, visibleInLegend: true} , 
                    1: {showR2: true, visibleInLegend: true}}
                    });

print(chartLog);

Here is the modified script: https://code.earthengine.google.com/7b1f46cad813cccc45e4b265a7f4e7ba

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.