Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reduce columns of ee.FeatureCollection by groups #374

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions geetools/ee_feature_collection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Toolbox for the `ee.FeatureCollection` class."""
from __future__ import annotations

from typing import Optional

import ee
import geopandas as gpd
from matplotlib import pyplot as plt
Expand Down Expand Up @@ -245,6 +247,59 @@ def byFeatures(

return ee.Dictionary.fromLists(features, values)

def reduceColumnsGroup(
self, reducer: ee.Reducer, groupBy: str = "system:index", selectors: Optional[list] = None
) -> ee.Dictionary:
"""Reduce a FeatureColletion column/s grouped by a key column.

Parameters:
reducer: The reducer.
groupBy: The column that will be used to group the output.
selectors: An optional list of columns to reduce. If None it will use all columns.

Returns:
a ee.Dictionary with the following structure:

{
'group1': {
'selector1': {
'reducer1_output': value1,
'reducer2_output': value2,
},
'selector2': {
'reducer1_output': value1,
'reducer2_output': value2,
},
},
'group2': {
'selector1': {
'reducer1_output': value1,
'reducer2_output': value2,
},
'selector2': {
'reducer1_output': value1,
'reducer2_output': value2,
},
},
}
"""
if selectors is None:
selectors = self._obj.first().propertyNames()
selectors = ee.List(selectors)
keys = self._obj.aggregate_array(groupBy).distinct()

def reduce_key(key):
filtered = self._obj.filter(ee.Filter.eq(groupBy, key))

def reduce_selector(sel):
return filtered.reduceColumns(reducer, [sel])

outputs = selectors.map(reduce_selector)
return ee.Dictionary.fromLists(selectors, outputs)

values = keys.map(reduce_key)
return ee.Dictionary.fromLists(keys, values)

def plot_by_features(
self,
type: str = "bar",
Expand Down
37 changes: 37 additions & 0 deletions tests/test_FeatureCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,43 @@ def vatican(self):
return ee.Geometry.Point([12.453386, 41.903282]).buffer(1)


class TestReduceColumnsGroup:
"""Test the ``reduceColumnsGroup`` method."""

def test_reduce_columns_group(self, data_regression):
red = ee.Reducer.mean().combine(ee.Reducer.sum(), sharedInputs=True)
output = self.table.geetools.reduceColumnsGroup(
reducer=red, groupBy="ADM0_NAME", selectors=["Shape_Area"] # group by country
)
data_regression.check(output.getInfo())

def test_reduce_columns_group_custom_output(self, data_regression):
red = ee.Reducer.mean().combine(ee.Reducer.sum(), sharedInputs=True)
red = red.setOutputs(["average_km2", "sum_km2"])
output = self.table.geetools.reduceColumnsGroup(
reducer=red, groupBy="ADM0_NAME", selectors=["Shape_Area"] # group by country
)
data_regression.check(output.getInfo())

def test_reduce_columns_group_fail_column_type(self):
red = ee.Reducer.mean()
output = self.table.geetools.reduceColumnsGroup(
reducer=red, groupBy="ADM0_NAME", selectors=["ADM1_NAME"] # group by country
)
with pytest.raises(ee.ee_exception.EEException) as excinfo:
output.getInfo()
assert (
str(excinfo.value)
== "Collection.reduceColumns: Can't set input 0 of MEAN to Aragatsotn.: Input must be a scalar number."
)

@property
def table(self):
return ee.FeatureCollection("FAO/GAUL/2015/level1").filter(
ee.Filter.stringStartsWith(leftField="ADM0_NAME", rightValue="Ar")
)


class TestAddId:
"""Test the ``addId`` method."""

Expand Down
16 changes: 16 additions & 0 deletions tests/test_FeatureCollection/test_reduce_columns_group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Argentina:
Shape_Area:
mean: 11.59538319268763
sum: 278.2891966245031
Armenia:
Shape_Area:
mean: 0.2852573993497455
sum: 3.1378313928472004
Aruba:
Shape_Area:
mean: 0.0149496718126
sum: 0.0149496718126
Arunachal Pradesh:
Shape_Area:
mean: 3.1213382042817
sum: 6.2426764085634
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Argentina:
Shape_Area:
average_km2: 11.59538319268763
sum_km2: 278.2891966245031
Armenia:
Shape_Area:
average_km2: 0.2852573993497455
sum_km2: 3.1378313928472004
Aruba:
Shape_Area:
average_km2: 0.0149496718126
sum_km2: 0.0149496718126
Arunachal Pradesh:
Shape_Area:
average_km2: 3.1213382042817
sum_km2: 6.2426764085634
Loading