@@ -246,6 +246,16 @@ def _generic_metrics(
246246 ]
247247 + ["risk" ]
248248 ]
249+
250+ if metric_name == "risk_contributions" and len (self ._snapshots ) > 2 :
251+ # If there is more than one Snapshot, we need to update the
252+ # contributions from previous periods for continuity
253+ # and to set the base risk from the first period
254+ # This is not elegant, but we need the concatenated metrics from each period,
255+ # so we can't do it in the calculators, and we need
256+ # to do it before caching in the private attribute
257+ tmp = self ._risk_contributions_post_treatment (tmp )
258+
249259 setattr (self , attr_name , tmp )
250260
251261 if self ._risk_disc_rates :
@@ -329,48 +339,55 @@ def risk_contributions_metrics(self, **kwargs) -> pd.DataFrame:
329339
330340 """
331341
332- tmp = self ._compute_metrics (
342+ return self ._compute_metrics (
333343 metric_name = "risk_contributions" ,
334344 metric_meth = "calc_risk_contributions_metric" ,
335345 ** kwargs ,
336346 )
337347
338- # If there is more than one Snapshot, we need to update the
339- # contributions from previous periods for continuity
340- # and to set the base risk from the first period
341- if len (self ._snapshots ) > 2 :
342- tmp .set_index (["group" , "date" , "measure" , "metric" ], inplace = True )
343- start_dates = [snap .date for snap in self ._snapshots [:- 1 ]]
344- end_dates = [
345- snap .date - to_offset (self .time_resolution )
346- for snap in self ._snapshots [1 :]
348+ def _risk_contributions_post_treatment (self , df ) -> pd .DataFrame :
349+ df .set_index (["group" , "date" , "measure" , "metric" ], inplace = True )
350+ start_dates = [snap .date for snap in self ._snapshots [:- 1 ]]
351+ end_dates = [
352+ snap .date - to_offset (self .time_resolution ) for snap in self ._snapshots [1 :]
353+ ]
354+ periods_dates = list (zip (start_dates , end_dates ))
355+ df .loc [pd .IndexSlice [:, :, :, "base risk" ]] = df .loc [
356+ pd .IndexSlice [
357+ :,
358+ pd .to_datetime (self .start_date ).to_period (self .time_resolution ),
359+ :,
360+ "base risk" ,
347361 ]
348- periods_dates = list (zip (start_dates , end_dates ))
349- tmp .loc [pd .IndexSlice [:, :, :, "base risk" ]] = tmp .loc [
350- pd .IndexSlice [:, str (self .start_date ), :, "base risk" ]
351- ].values
352- for p2 in periods_dates [1 :]:
353- for metric in [
354- "exposure contribution" ,
355- "hazard contribution" ,
356- "vulnerability contribution" ,
357- "interaction contribution" ,
358- ]:
359- mask_last_previous = (
360- tmp .index .get_level_values (1 ).date == p2 [0 ]
361- ) & (tmp .index .get_level_values (3 ) == metric )
362- mask_to_update = (
363- (tmp .index .get_level_values (1 ).date > p2 [0 ])
364- & (tmp .index .get_level_values (1 ).date <= p2 [1 ])
365- & (tmp .index .get_level_values (3 ) == metric )
362+ ].values
363+ for p2 in periods_dates [1 :]:
364+ for metric in [
365+ "exposure contribution" ,
366+ "hazard contribution" ,
367+ "vulnerability contribution" ,
368+ "interaction contribution" ,
369+ ]:
370+ mask_last_previous = (
371+ df .index .get_level_values (1 )
372+ == pd .to_datetime (p2 [0 ]).to_period (self .time_resolution )
373+ ) & (df .index .get_level_values (3 ) == metric )
374+ mask_to_update = (
375+ (
376+ df .index .get_level_values (1 )
377+ > pd .to_datetime (p2 [0 ]).to_period (self .time_resolution )
366378 )
379+ & (
380+ df .index .get_level_values (1 )
381+ <= pd .to_datetime (p2 [1 ]).to_period (self .time_resolution )
382+ )
383+ & (df .index .get_level_values (3 ) == metric )
384+ )
367385
368- tmp .loc [mask_to_update , "risk" ] += tmp .loc [
369- mask_last_previous , "risk"
370- ].iloc [0 ]
386+ df .loc [mask_to_update , "risk" ] += df .loc [
387+ mask_last_previous , "risk"
388+ ].iloc [0 ]
371389
372- tmp .reset_index (inplace = True )
373- return tmp .drop ("index" , axis = 1 , errors = "ignore" )
390+ return df .reset_index ()
374391
375392 def per_date_risk_metrics (
376393 self ,
0 commit comments