Calculate probabilistic impact yearset#

This module generates a yearly impact object yimp which contains probabilistic annual impacts for a specified amount of years (sampled_years). The impact values are extracted from a given impact imp object that contains impact values per event. The amount of sampled years as a list of years (sampled_years) to be sampled for. The amount of events per sampled year (events_per_year) are determined with a Poisson distribution (lam = sum(event_impacts.frequency)). Then, the events occurring in each sampled year are sampled from the input imp object and summed up per year. Thus, the yimp object contains the sum of sampled (event) impacts for each sampled year. In contrast to the expected annual impact (eai), an yimp object contains an impact for EACH sampled year and this value differs among years. The number of events_per_year and the selected_events are saved in a sampling vector (sampling_vect).

The function impact_yearset performs all these computational steps, taking an imp and the list of sampled_years (sampled_years) as input. The output of the function is the yimp object and the sampling_vect. Moreover, a sampling_vect (generated in a previous run) can be provided as optional input and the user can custom-define the Poisson parameter lam. Reapplying the same sampling_vect does not only allow to reproduce the generated yimp, but also for a physically consistent way of sampling impacts caused by different hazards.

Sampling options. Per default, impact events are sampled without replacement (given that the original impact object contains enough events). When setting with_replacement=True, the impact events are sampled with replacement . Note that sampling without replacement can lead to distorted sampling if the frequencies of the different impacts (imp.frequency) are not equal.

Correction factor. By default, a correction factor is applied uniformly to all yearly impacts, such that the final yimp object has the same average annual impact than imp, the original impact object. Applying the correction factor can be avoided by setting correction_fac=False.

To make the process more transparent, this tutorial shows the single computations that are performed when generating an yimp object for a dummy event_impacts object.

import numpy as np
import climada.util.yearsets as yearsets
from climada.engine import Impact

# dummy event_impacts object containing 12 event impacts
imp = Impact(
    event_id=np.arange(6) + 10,
    event_name=np.arange(6) + 10,
    date=np.arange(6),
    coord_exp=np.array([[1, 2], [1.5, 2.5]]),
    eai_exp=np.array([13.4, 13.4]),
    at_event=np.array([0, 2, 4, 6, 60, 62]),
    frequency=np.full(6, 0.2),
    aai_agg=26.8,
)

Step-by-step calculation#

# the number of years to sample impacts for (length(yimp.at_event) = n_sampled_years)
n_sampled_years = 10

# sample number of events per sampled year
lam = np.sum(imp.frequency)
events_per_year = yearsets.sample_from_poisson(n_sampled_years, lam)
events_per_year
array([0, 1, 1, 0, 2, 3, 3, 0, 2, 3])
# generate the sampling vector
sampling_vect = yearsets.sample_events(events_per_year, imp.frequency)
sampling_vect
[array([], dtype=int64),
 array([0]),
 array([1]),
 array([], dtype=int64),
 array([4, 2]),
 array([2, 0, 4]),
 array([5, 1, 3]),
 array([], dtype=int64),
 array([5, 3]),
 array([5, 3, 1])]
# calculate the impact per year
imp_per_year = yearsets.compute_imp_per_year(imp, sampling_vect)
imp_per_year
array([ 0,  0,  2,  0, 64, 64, 70,  0, 68, 70])
# calculate the correction factor
correction_factor = yearsets.calculate_correction_fac(imp_per_year, imp)
correction_factor
0.7928994082840237

Direct calculation#

If we use the same seed, the yimp.at_event values coincide with the step-by-step imp_per_year values, if no correction factor is applied.

example_seed = 12345  # fix a seed
sampled_years = list(range(2015, 2025))

# direct computation
yimp, sampling_vect = yearsets.impact_yearset(
    imp, sampled_years, correction_fac=False, seed=example_seed
)

# step-by-step computation without applying the correction factor
events_per_year = yearsets.sample_from_poisson(
    len(sampled_years), lam, seed=example_seed
)
sampling_vect = yearsets.sample_events(
    events_per_year, imp.frequency, seed=example_seed
)
imp_per_year = yearsets.compute_imp_per_year(imp, sampling_vect)


print("yimp.at_event = ", yimp.at_event)
print("imp_per_year = ", imp_per_year)
print(
    f"The expected annual impact {round(yimp.aai_agg,2)} differs from the one of the original impact ({round(imp.aai_agg,2)})."
)
yimp.at_event =  [  2   0   0  70 130   0   0 128  68  62]
imp_per_year =  [  2   0   0  70 130   0   0 128  68  62]
The expected annual impact 46.0 differs from the one of the original impact (26.8).

Similarly, if we use the same seed, the yimp.at_event values when using the correction factor coincide with the step-by-step imp_per_year values after applyng the correction factor.

# direct computation
yimp, sampling_vect = yearsets.impact_yearset(
    imp, sampled_years, correction_fac=True, seed=example_seed
)

# compute correction factor from imp_per_year computed above without correction factor
correction_factor = yearsets.calculate_correction_fac(imp_per_year, imp)

print("yimp.at_event = ", np.round(yimp.at_event, 2))
print("imp_per_year = ", np.round(imp_per_year * correction_factor, 2))
print(
    f"The expected annual impact {round(yimp.aai_agg,2)} is equal to the one of the original impact ({round(imp.aai_agg,2)})."
)
2025-09-19 15:39:54,743 - climada.util.yearsets - INFO - The correction factor is 0.5826086956521739.
yimp.at_event =  [ 1.17  0.    0.   40.78 75.74  0.    0.   74.57 39.62 36.12]
imp_per_year =  [ 1.17  0.    0.   40.78 75.74  0.    0.   74.57 39.62 36.12]
The expected annual impact 26.8 is equal to the one of the original impact (26.8).