From 3e0c87ad6be3279597aa607daee196762863199a Mon Sep 17 00:00:00 2001 From: Stefan Blumentrath Date: Mon, 15 May 2023 12:44:34 +0200 Subject: [PATCH] r.univar: print only statistics for existing zones (#2957) * skip zones without pixels * add test for zones with gaps --- raster/r.univar/stats.c | 4 ++ raster/r.univar/testsuite/test_r_univar.py | 70 +++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/raster/r.univar/stats.c b/raster/r.univar/stats.c index 1e061471c6e..ad48786bbcf 100644 --- a/raster/r.univar/stats.c +++ b/raster/r.univar/stats.c @@ -116,6 +116,10 @@ int print_stats(univar_stat *stats) unsigned int i; size_t qpos_25, qpos_75, *qpos_perc; + /* stats collected for this zone? */ + if (stats[z].size == 0) + continue; + /* all these calculations get promoted to doubles, so any DIV0 becomes * nan */ mean = stats[z].sum / stats[z].n; diff --git a/raster/r.univar/testsuite/test_r_univar.py b/raster/r.univar/testsuite/test_r_univar.py index 34437261408..02678c5115b 100644 --- a/raster/r.univar/testsuite/test_r_univar.py +++ b/raster/r.univar/testsuite/test_r_univar.py @@ -20,6 +20,7 @@ def tearDown(self): self.runModule("g.remove", flags="f", type="raster", name="map_a") self.runModule("g.remove", flags="f", type="raster", name="map_b") self.runModule("g.remove", flags="f", type="raster", name="zone_map") + self.runModule("g.remove", flags="f", type="raster", name="zone_map_with_gap") def setUp(self): """Create input data""" @@ -31,7 +32,12 @@ def setUp(self): "r.mapcalc", expression="map_b = 200 + row() + col()", overwrite=True ) self.runModule( - "r.mapcalc", expression="zone_map = if(row() < 20, 1,2)", overwrite=True + "r.mapcalc", expression="zone_map = if(row() < 20, 1, 2)", overwrite=True + ) + self.runModule( + "r.mapcalc", + expression="zone_map_with_gap = if(row()> 20, 2, 9)", + overwrite=True, ) def test_1(self): @@ -382,6 +388,68 @@ def test_3_zone(self): sep="=", ) + def test_zone_with_gap_in_cats(self): + """ + test if gaps in categories in a map are not included in the output + :return: + """ + + # Output of r.univar + univar_string = """zone=2; + n=12600 + null_cells=0 + cells=12600 + min=122 + max=380 + range=258 + mean=251 + mean_of_abs=251 + stddev=59.8595578555895 + variance=3583.16666666667 + coeff_var=23.8484294245376 + sum=3162600 + first_quartile=201 + median=251 + third_quartile=301 + percentile_90=331 + zone=9; + n=3600 + null_cells=0 + cells=12600 + min=102 + max=310 + range=208 + mean=206 + mean_of_abs=206 + stddev=56.6406803160649 + variance=3208.16666666667 + coeff_var=27.4954758815849 + sum=741600 + first_quartile=156 + median=206 + third_quartile=256 + percentile_90=283""" + + self.assertModuleKeyValue( + module="r.univar", + map=["map_a", "map_b"], + zones="zone_map_with_gap", + flags="ge", + reference=univar_string, + precision=6, + sep="=", + ) + self.assertModuleKeyValue( + module="r.univar", + map=["map_a", "map_b"], + zones="zone_map_with_gap", + flags="ge", + nprocs=4, + reference=univar_string, + precision=6, + sep="=", + ) + class TestAccumulateFails(TestCase): def test_error_handling(self):