Views
No views yet



1# Create successful summit metric per member and per expedition
2def create_target_variables(df):
3 df = df.copy()
4
5 # Calculate mean summit days per peak
6 peak_smtdays_mean = df.groupby('peakid')['smtdays'].mean().reset_index()
7 peak_smtdays_mean.columns = ['peakid', 'peak_mean_smtdays']
8
9 # Merge back to main dataframe
10 df = df.merge(peak_smtdays_mean, on='peakid', how='left')
11
12 # Calculate difference from peak mean (peak_mean - smtdays)
13 df['smtdays_to_mean_peak'] = df['peak_mean_smtdays'] - df['smtdays']
14
15 # High point to summit
16 df['highpoint_summit'] = df['heightm'] - df['highpoint']
17
18 # Create success_on_route: True if any of the 4 success columns is True
19 df['success_on_route'] = df[['success1', 'success2', 'success3', 'success4']].any(axis=1)
20
21 # Winter ascent
22 df['winter_ascent'] = df['season'] == 'Winter'
23
24 # expedition success
25 df['min_one_summit_by_member'] = df['members_summited'] > 0
26 df['member_summit_ratio'] = df['members_summited'] / df['total_members']
27
28 df.loc[df['members_summited'] > 0, 'summited_death_ratio'] = (
29 df.loc[df['members_summited'] > 0, 'members_deaths'] /
30 df.loc[df['members_summited'] > 0, 'members_summited']
31 )
32
33 # Numerical success score (0-100)
34 df['expedition_success_score'] = 0.0 # Default for failed expeditions
35
36 # For successful expeditions, calculate score
37 successful_mask = df['success_on_route']
38 df.loc[successful_mask, 'expedition_success_score'] = (
39 1 + # Base score for completing route
40 np.minimum(100, df.loc[successful_mask, 'member_summit_ratio'].fillna(0) * 10) - # Overall Exped summit ratio bonus
41 np.minimum(40, df.loc[successful_mask, 'members_deaths'].fillna(0) * 100) - # Member death penalty
42 np.minimum(60, df.loc[successful_mask, 'hired_deaths'].fillna(0) * 200) + # Hired member death penalty
43 df.loc[successful_mask, 'msolo'] * 400 + # Solo achievement bonus
44 df.loc[successful_mask, 'mspeed'] * 100 + # Speed achievement bonus
45 df.loc[successful_mask, 'msuccess'] * 20 + # Individual success achievement bonus
46 df.loc[successful_mask, 'mtraverse'] * 10 - # Traverse achievement bonus
47 df.loc[successful_mask, 'disputed'] * 100 + # Disputed penalty
48 df.loc[successful_mask, 'disabled'] * 200 + # Disabled bonus
49 (df.loc[successful_mask, 'oxygen_required'] * df.loc[successful_mask, 'mo2none'] * 50) + # No O2 bonus - added logic to check to see if peak trad requires o2
50 (df.loc[successful_mask, 'oxygen_required'] * df.loc[successful_mask, 'o2none'] * 50) + # Exped no O2 bonus
51 df.loc[successful_mask, 'winter_ascent'] * 100 + # Winter ascent bonus
52 df.loc[successful_mask, 'smtdays_to_mean_peak'] * 10 + # Add timeframe bonus
53 df.loc[successful_mask, 'summit_approach_severe_weather_hours'] * 1.4 +
54 df.loc[successful_mask, 'summit_approach_extreme_cold_hours'] * 1.4 +
55 df.loc[successful_mask, 'summit_approach_high_wind_hours'] +
56 df.loc[successful_mask, 'summit_approach_precip_total'] * 1.4 +
57 df.loc[successful_mask, 'summit_approach_temp_min'] * -1.4 +
58 df.loc[successful_mask, 'full_wind_max'] +
59 df.loc[successful_mask, 'full_weather_code_mode'] +
60 df.loc[successful_mask, 'full_precip_total'] +
61 df.loc[successful_mask, 'full_extreme_cold_hours'] * 1.4 +
62 df.loc[successful_mask, 'full_high_wind_hours'] +
63 df.loc[successful_mask, 'full_low_visibility_hours'] * 1.4 -
64 df.loc[successful_mask, 'death_day_severe_weather_hours'] * 100 -
65 df.loc[successful_mask, 'death_day_extreme_cold_hours'] * 100 -
66 df.loc[successful_mask, 'death_day_high_wind_hours'] * 100 -
67 df.loc[successful_mask, 'death_day_low_visibility_hours'] * 100 +
68 df.loc[successful_mask, 'decision_window_precip_total'] * 1.4 +
69 df.loc[successful_mask, 'decision_window_temp_min'] * -1.4 +
70 df.loc[successful_mask, 'early_phase_low_visibility_hours'] * 1.4 +
71 df.loc[successful_mask, 'smttime'] / 2 #
72 )
73
74 # For unsuccessful expeditions, calculate negative score
75 unsuccessful_mask = ~df['success_on_route']
76 df.loc[unsuccessful_mask, 'expedition_failure_score'] = (
77 -10 - # Base negative score for failed route
78 np.maximum(100, df.loc[unsuccessful_mask, 'members_deaths'].fillna(0) * 100) - # Member death penalty
79 np.maximum(200, df.loc[unsuccessful_mask, 'hired_deaths'].fillna(0) * 200) + # Hired member death penalty
80 np.minimum(10, df.loc[unsuccessful_mask, 'member_summit_ratio'].fillna(0) * 2) - # Member summit ratio bonus for partial success
81 df.loc[unsuccessful_mask, 'death'] * 80 + # penalty for dying
82 (df.loc[unsuccessful_mask, 'oxygen_required'] * df.loc[unsuccessful_mask, 'mo2none'] * 100) + # No O2 bonus for risk-taking
83 (df.loc[unsuccessful_mask, 'oxygen_required'] * df.loc[unsuccessful_mask, 'o2none'] * 100) + # Exped no O2 bonus for risk-taking
84 df.loc[unsuccessful_mask, 'disabled'] * 20 + # Disabled bonus (reduced from success case)
85 df.loc[unsuccessful_mask, 'winter_ascent'] * 120 + # Winter ascent risk bonus (reduced from success case)
86 df.loc[unsuccessful_mask, 'smtdays_to_mean_peak'] * 10 - # Reduced timeframe bonus
87 df.loc[unsuccessful_mask, 'disputed'] * 50 - # Reduced disputed penalty
88 df.loc[unsuccessful_mask, 'rope'] / 4 - # penalty for resources used
89 df.loc[unsuccessful_mask, 'camps'] * 16 - # penalty for resources used
90 df.loc[unsuccessful_mask, 'death_day_severe_weather_hours'] * 50 - # penalty for death on severe weather day
91 df.loc[unsuccessful_mask, 'death_day_extreme_cold_hours'] * 5 -
92 df.loc[unsuccessful_mask, 'death_day_high_wind_hours'] * 50 +
93 df.loc[unsuccessful_mask, 'mperhighpt'] / 100 - # bonus for member high point
94 df.loc[unsuccessful_mask, 'decision_window_precip_hours'] * 10 - # bad decision making
95 df.loc[unsuccessful_mask, 'decision_window_severe_weather_hours'] * 10 +
96 df.loc[unsuccessful_mask, 'smttime'] / 10 -
97 df.loc[unsuccessful_mask, 'total_hired'] * 4 - # penalty for all those hired
98 df.loc[unsuccessful_mask, 'deathhgtm'] / 10 # death hight penalty
99 )
100
101 # Create a combined score column
102 df['expedition_score'] = df['expedition_success_score'].fillna(0) + df['expedition_failure_score'].fillna(0)
103
104 return df
105
106pre_fe_df = create_target_variables(final_df_with_weather)
107