Skip to content

Commit ce2f0bf

Browse files
committed
Add image_byClass function
1 parent 57fa6d8 commit ce2f0bf

File tree

1 file changed

+283
-21
lines changed

1 file changed

+283
-21
lines changed

geemap/chart.py

Lines changed: 283 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,18 @@ def setChartType(
106106
x_cols = [self.df.columns[0]]
107107
if y_cols is None:
108108
y_cols = [self.df.columns[1]]
109-
if title is None:
110-
title = chart_type
109+
110+
if isinstance(x_cols, str):
111+
x_cols = [x_cols]
112+
113+
if isinstance(y_cols, str):
114+
y_cols = [y_cols]
115+
116+
if len(x_cols) == 1 and len(y_cols) > 1:
117+
x_cols = x_cols * len(y_cols)
118+
119+
if title is not None:
120+
kwargs["title"] = title
111121

112122
if chart_type == "PieChart":
113123
if colors is None:
@@ -142,6 +152,12 @@ def setChartType(
142152
color = colors[
143153
i % len(colors)
144154
] # Cycle through colors if not enough are provided
155+
if "display_legend" not in kwargs and len(y_cols) > 1:
156+
kwargs["display_legend"] = True
157+
kwargs["labels"] = [y_col]
158+
else:
159+
kwargs["labels"] = [y_col]
160+
145161
if chart_type == "ScatterChart":
146162
marks.append(
147163
bq.Scatter(
@@ -216,10 +232,9 @@ def setChartType(
216232
else:
217233
raise ValueError("Unsupported chart type")
218234

219-
self.chart = bq.Figure(marks=marks, title=title, **kwargs)
220235
x_axis = bq.Axis(scale=x_sc, label=x_label)
221236
y_axis = bq.Axis(scale=y_sc, orientation="vertical", label=y_label)
222-
self.chart.axes = [x_axis, y_axis]
237+
self.chart = bq.Figure(marks=marks, axes=[x_axis, y_axis], **kwargs)
223238

224239
return self
225240

@@ -772,10 +787,65 @@ def grow_bin(bin_size, ref):
772787

773788

774789
def image_byClass(
775-
image, classBand, region, reducer, scale, classLabels, xLabels, **kwargs
790+
image,
791+
classBand,
792+
region,
793+
reducer="MEAN",
794+
scale=None,
795+
classLabels=None,
796+
xLabels=None,
797+
chart_type="LineChart",
798+
**kwargs,
776799
):
777-
# TODO
778-
pass
800+
"""
801+
Generates a Chart from an image by class. Extracts and plots band values by
802+
class.
803+
804+
Args:
805+
image (ee.Image): Image to extract band values from.
806+
classBand (str): The band name to use as class labels.
807+
region (ee.Geometry | ee.FeatureCollection): The region(s) to reduce.
808+
reducer (str | ee.Reducer): The reducer type for zonal statistics. Can
809+
be one of 'mean', 'median', 'sum', 'min', 'max', etc.
810+
scale (int): The scale in meters at which to perform the analysis.
811+
classLabels (list): List of class labels.
812+
xLabels (list): List of x-axis labels.
813+
chart_type (str): The type of chart to create. Supported types are
814+
'ScatterChart', 'LineChart', 'ColumnChart', 'BarChart', 'PieChart',
815+
'AreaChart', and 'Table'.
816+
**kwargs: Additional keyword arguments.
817+
818+
Returns:
819+
None
820+
"""
821+
fc = zonal_stats(
822+
image, region, stat_type=reducer, scale=scale, verbose=False, return_fc=True
823+
)
824+
bands = image.bandNames().getInfo()
825+
df = ee_to_df(fc)[bands + [classBand]]
826+
827+
df_transposed = df.set_index(classBand).T
828+
829+
if xLabels is not None:
830+
df_transposed["label"] = xLabels
831+
else:
832+
df_transposed["label"] = df_transposed.index
833+
834+
if classLabels is None:
835+
y_cols = df_transposed.columns.tolist()
836+
y_cols.remove("label")
837+
else:
838+
y_cols = classLabels
839+
840+
fig = BaseChart(df_transposed)
841+
fig.setChartType(
842+
chart_type,
843+
x_cols="label",
844+
y_cols=y_cols,
845+
**kwargs,
846+
)
847+
848+
return fig.chart
779849

780850

781851
def image_byRegion(image, regions, reducer, scale, xProperty, **kwargs):
@@ -812,8 +882,45 @@ def image_doySeries(
812882
endDay,
813883
**kwargs,
814884
):
815-
# TODO
816-
pass
885+
"""
886+
Generates a time series chart of an image collection for a specific region over a range of days of the year.
887+
888+
Args:
889+
imageCollection (ee.ImageCollection): The image collection to analyze.
890+
region (ee.Geometry | ee.FeatureCollection): The region to reduce.
891+
regionReducer (str | ee.Reducer): The reducer type for zonal statistics. Can be one of 'mean', 'median', 'sum', 'min', 'max', etc.
892+
scale (int): The scale in meters at which to perform the analysis.
893+
yearReducer (str | ee.Reducer): The reducer type for yearly statistics.
894+
startDay (int): The start day of the year.
895+
endDay (int): The end day of the year.
896+
**kwargs: Additional keyword arguments.
897+
898+
Returns:
899+
None
900+
"""
901+
series = imageCollection.filter(
902+
ee.Filter.calendarRange(startDay, endDay, "day_of_year")
903+
)
904+
fc = zonal_stats(
905+
series,
906+
region,
907+
stat_type=regionReducer,
908+
scale=scale,
909+
verbose=False,
910+
return_fc=True,
911+
)
912+
df = ee_to_df(fc)
913+
years = df["year"].unique()
914+
values = {
915+
year: df[df["year"] == year].drop(columns=["year"]).mean() for year in years
916+
}
917+
918+
# Creating a dataframe to hold the results
919+
result_df = pd.DataFrame(values).T
920+
921+
# Plotting the results
922+
line_chart = LineChart(result_df, years.tolist(), **kwargs)
923+
line_chart.plot_chart()
817924

818925

819926
def image_doySeriesByRegion(
@@ -828,8 +935,39 @@ def image_doySeriesByRegion(
828935
endDay,
829936
**kwargs,
830937
):
831-
# TODO
832-
pass
938+
"""
939+
Generates a time series chart of an image collection for multiple regions over a range of days of the year.
940+
941+
Args:
942+
imageCollection (ee.ImageCollection): The image collection to analyze.
943+
bandName (str): The name of the band to analyze.
944+
regions (ee.FeatureCollection): The regions to analyze.
945+
regionReducer (str | ee.Reducer): The reducer type for zonal statistics.
946+
scale (int): The scale in meters at which to perform the analysis.
947+
yearReducer (str | ee.Reducer): The reducer type for yearly statistics.
948+
seriesProperty (str): The property to use for labeling the series.
949+
startDay (int): The start day of the year.
950+
endDay (int): The end day of the year.
951+
**kwargs: Additional keyword arguments.
952+
953+
Returns:
954+
None
955+
"""
956+
series = imageCollection.filter(
957+
ee.Filter.calendarRange(startDay, endDay, "day_of_year")
958+
)
959+
fc = zonal_stats(
960+
series,
961+
regions,
962+
stat_type=regionReducer,
963+
scale=scale,
964+
verbose=False,
965+
return_fc=True,
966+
)
967+
bands = [bandName] + [seriesProperty]
968+
df = ee_to_df(fc)[bands]
969+
line_chart = Feature_ByProperty(df, [bandName], seriesProperty, **kwargs)
970+
line_chart.plot_chart()
833971

834972

835973
def image_doySeriesByYear(
@@ -843,29 +981,153 @@ def image_doySeriesByYear(
843981
endDay,
844982
**kwargs,
845983
):
846-
# TODO
847-
pass
984+
"""
985+
Generates a time series chart of an image collection for a specific region over multiple years.
986+
987+
Args:
988+
imageCollection (ee.ImageCollection): The image collection to analyze.
989+
bandName (str): The name of the band to analyze.
990+
region (ee.Geometry | ee.FeatureCollection): The region to analyze.
991+
regionReducer (str | ee.Reducer): The reducer type for zonal statistics.
992+
scale (int): The scale in meters at which to perform the analysis.
993+
sameDayReducer (str | ee.Reducer): The reducer type for daily statistics.
994+
startDay (int): The start day of the year.
995+
endDay (int): The end day of the year.
996+
**kwargs: Additional keyword arguments.
997+
998+
Returns:
999+
None
1000+
"""
1001+
series = imageCollection.filter(
1002+
ee.Filter.calendarRange(startDay, endDay, "day_of_year")
1003+
)
1004+
fc = zonal_stats(
1005+
series,
1006+
region,
1007+
stat_type=regionReducer,
1008+
scale=scale,
1009+
verbose=False,
1010+
return_fc=True,
1011+
)
1012+
bands = [bandName, "year"]
1013+
df = ee_to_df(fc)[bands]
1014+
line_chart = Feature_ByProperty(df, [bandName], "year", **kwargs)
1015+
line_chart.plot_chart()
8481016

8491017

8501018
def image_histogram(
8511019
image, region, scale, maxBuckets, minBucketWidth, maxRaw, maxPixels, **kwargs
8521020
):
853-
# TODO
854-
pass
1021+
"""
1022+
Generates a histogram from an image.
1023+
1024+
Args:
1025+
image (ee.Image): The image to analyze.
1026+
region (ee.Geometry | ee.FeatureCollection): The region to analyze.
1027+
scale (int): The scale in meters at which to perform the analysis.
1028+
maxBuckets (int): The maximum number of buckets (bins) to use when building a histogram.
1029+
minBucketWidth (float): The minimum histogram bucket width, or null to allow any power of 2.
1030+
maxRaw (int): The maximum number of pixels to reduce at one time.
1031+
maxPixels (int): The maximum number of pixels to reduce.
1032+
**kwargs: Additional keyword arguments.
1033+
1034+
Returns:
1035+
None
1036+
"""
1037+
fc = zonal_stats(
1038+
image,
1039+
region,
1040+
stat_type="count",
1041+
scale=scale,
1042+
max_pixels=maxPixels,
1043+
max_raw=maxRaw,
1044+
verbose=False,
1045+
return_fc=True,
1046+
)
1047+
df = ee_to_df(fc)
1048+
bands = image.bandNames().getInfo()
1049+
for band in bands:
1050+
feature_histogram(df, band, maxBuckets, minBucketWidth, **kwargs)
8551051

8561052

8571053
def image_regions(image, regions, reducer, scale, seriesProperty, xLabels, **kwargs):
858-
# TODO
859-
pass
1054+
"""
1055+
Generates a Chart from an image by regions. Extracts and plots band values in multiple regions.
1056+
1057+
Args:
1058+
image (ee.Image): Image to extract band values from.
1059+
regions (ee.FeatureCollection | ee.Geometry): Regions to reduce. Defaults to the image's footprint.
1060+
reducer (str | ee.Reducer): The reducer type for zonal statistics. Can be one of 'mean', 'median', 'sum', 'min', 'max', etc.
1061+
scale (int): The scale in meters at which to perform the analysis.
1062+
seriesProperty (str): The property to use for labeling the series.
1063+
xLabels (list): List of x-axis labels.
1064+
**kwargs: Additional keyword arguments.
1065+
1066+
Returns:
1067+
None
1068+
"""
1069+
fc = zonal_stats(
1070+
image, regions, stat_type=reducer, scale=scale, verbose=False, return_fc=True
1071+
)
1072+
bands = image.bandNames().getInfo()
1073+
df = ee_to_df(fc)[bands + [seriesProperty]]
1074+
feature_groups(df, seriesProperty, bands, seriesProperty, **kwargs)
8601075

8611076

8621077
def image_series(imageCollection, region, reducer, scale, xProperty, **kwargs):
863-
# TODO
864-
pass
1078+
"""
1079+
Generates a time series chart of an image collection for a specific region.
1080+
1081+
Args:
1082+
imageCollection (ee.ImageCollection): The image collection to analyze.
1083+
region (ee.Geometry | ee.FeatureCollection): The region to reduce.
1084+
reducer (str | ee.Reducer): The reducer type for zonal statistics. Can be one of 'mean', 'median', 'sum', 'min', 'max', etc.
1085+
scale (int): The scale in meters at which to perform the analysis.
1086+
xProperty (str): The name of the property to use as the x-axis values.
1087+
**kwargs: Additional keyword arguments.
1088+
1089+
Returns:
1090+
None
1091+
"""
1092+
fc = zonal_stats(
1093+
imageCollection,
1094+
region,
1095+
stat_type=reducer,
1096+
scale=scale,
1097+
verbose=False,
1098+
return_fc=True,
1099+
)
1100+
bands = imageCollection.first().bandNames().getInfo()
1101+
df = ee_to_df(fc)[bands + [xProperty]]
1102+
feature_byFeature(df, xProperty, bands, **kwargs)
8651103

8661104

8671105
def image_seriesByRegion(
8681106
imageCollection, regions, reducer, band, scale, xProperty, seriesProperty, **kwargs
8691107
):
870-
# TODO
871-
pass
1108+
"""
1109+
Generates a time series chart of an image collection for multiple regions.
1110+
1111+
Args:
1112+
imageCollection (ee.ImageCollection): The image collection to analyze.
1113+
regions (ee.FeatureCollection | ee.Geometry): The regions to reduce.
1114+
reducer (str | ee.Reducer): The reducer type for zonal statistics.
1115+
band (str): The name of the band to analyze.
1116+
scale (int): The scale in meters at which to perform the analysis.
1117+
xProperty (str): The name of the property to use as the x-axis values.
1118+
seriesProperty (str): The property to use for labeling the series.
1119+
**kwargs: Additional keyword arguments.
1120+
1121+
Returns:
1122+
None
1123+
"""
1124+
fc = zonal_stats(
1125+
imageCollection,
1126+
regions,
1127+
stat_type=reducer,
1128+
scale=scale,
1129+
verbose=False,
1130+
return_fc=True,
1131+
)
1132+
df = ee_to_df(fc)[[band, xProperty, seriesProperty]]
1133+
feature_groups(df, xProperty, band, seriesProperty, **kwargs)

0 commit comments

Comments
 (0)