Skip to content

Commit 3b4048e

Browse files
committed
Add quantile and median for impact forecast
1 parent b11e9c5 commit 3b4048e

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

climada/engine/impact_forecast.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,54 @@ def mean(self):
376376
imp_mat=red_imp_mat,
377377
haz_type=self.haz_type,
378378
)
379+
380+
def quantile(self, q: float):
381+
"""
382+
Reduce the impact matrix and at_event of an ImpactForecast to the quantile value.
383+
384+
Parameters
385+
----------
386+
q : float
387+
The quantile to compute, which must be between 0 and 1.
388+
389+
Returns
390+
-------
391+
ImpactForecast
392+
An ImpactForecast object with the quantile impact matrix and at_event.
393+
"""
394+
red_imp_mat = sparse.csr_matrix(np.quantile(self.imp_mat.toarray(), q, axis=0))
395+
red_at_event = np.array([red_imp_mat.sum()])
396+
reduced_attrs = self._reduce_attrs(f"quantile_{q}")
397+
return ImpactForecast(
398+
lead_time=reduced_attrs["lead_time"],
399+
member=reduced_attrs["member"],
400+
event_id=reduced_attrs["event_id"],
401+
event_name=reduced_attrs["event_name"],
402+
date=reduced_attrs["date"],
403+
frequency=reduced_attrs["frequency"],
404+
frequency_unit=self.frequency_unit,
405+
coord_exp=self.coord_exp,
406+
crs=self.crs,
407+
eai_exp=self.eai_exp,
408+
at_event=red_at_event,
409+
tot_value=self.tot_value,
410+
aai_agg=self.aai_agg,
411+
unit=self.unit,
412+
imp_mat=red_imp_mat,
413+
haz_type=self.haz_type,
414+
)
415+
416+
def median(self):
417+
"""
418+
Reduce the impact matrix and at_event of an ImpactForecast to the median value.
419+
420+
Parameters
421+
----------
422+
None
423+
424+
Returns
425+
-------
426+
ImpactForecast
427+
An ImpactForecast object with the median impact matrix and at_event.
428+
"""
429+
return self.quantile(0.5)

climada/engine/test/test_impact_forecast.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,32 @@ def test_impact_forecast_mean_min_max(impact_forecast):
261261
assert imp_fcst_mean.date == 0
262262
assert imp_fcst_min.date == 0
263263
assert imp_fcst_max.date == 0
264+
265+
266+
def test_impact_forecast_quantile(impact_forecast):
267+
"""Check quantile method for ImpactForecast"""
268+
for q in [0.0, 0.5, 0.8]:
269+
imp_fcst_quantile = impact_forecast.quantile(q)
270+
271+
# assert imp_mat
272+
npt.assert_array_equal(
273+
imp_fcst_quantile.imp_mat.toarray().squeeze(),
274+
np.quantile(impact_forecast.imp_mat.toarray(), q, axis=0),
275+
)
276+
# assert at_event
277+
npt.assert_array_equal(
278+
imp_fcst_quantile.at_event,
279+
np.quantile(impact_forecast.at_event, q, axis=0).sum(),
280+
)
281+
282+
# check that attributes where reduced correctly
283+
npt.assert_array_equal(imp_fcst_quantile.member, np.array([-1]))
284+
npt.assert_array_equal(
285+
imp_fcst_quantile.lead_time, np.array([np.timedelta64("NaT")])
286+
)
287+
npt.assert_array_equal(imp_fcst_quantile.event_id, np.array([0]))
288+
npt.assert_array_equal(
289+
imp_fcst_quantile.event_name, np.array([f"quantile_{q}"])
290+
)
291+
npt.assert_array_equal(imp_fcst_quantile.frequency, np.array([1]))
292+
npt.assert_array_equal(imp_fcst_quantile.date, np.array([0]))

0 commit comments

Comments
 (0)