James McCool commited on
Commit
d015d8c
·
1 Parent(s): 8b34fed

Add reassess_edge function in reassess_edge.py for recalculating lineup metrics based on player performance, and update app.py to utilize this function for improved edge assessments in player lineups.

Browse files
Files changed (2) hide show
  1. app.py +2 -1
  2. global_func/reassess_edge.py +61 -5
app.py CHANGED
@@ -26,6 +26,7 @@ from global_func.reduce_volatility_preset import reduce_volatility_preset
26
  from global_func.analyze_player_combos import analyze_player_combos
27
  from global_func.stratification_function import stratification_function
28
  from global_func.exposure_spread import exposure_spread
 
29
 
30
  freq_format = {'Finish_percentile': '{:.2%}', 'Lineup Edge': '{:.2%}', 'Win%': '{:.2%}'}
31
  stacking_sports = ['MLB', 'NHL', 'NFL', 'LOL']
@@ -1526,7 +1527,7 @@ with tab2:
1526
  st.session_state['export_base']['salary'] = st.session_state['export_base']['salary'].astype('uint16')
1527
 
1528
  print(st.session_state['export_base'].head(10))
1529
- st.session_state['export_base'] = predict_dupes(st.session_state['export_base'], st.session_state['map_dict'], site_var, type_var, Contest_Size, strength_var, sport_var)
1530
  st.session_state['export_merge'] = st.session_state['export_base'].copy()
1531
 
1532
  with st.container():
 
26
  from global_func.analyze_player_combos import analyze_player_combos
27
  from global_func.stratification_function import stratification_function
28
  from global_func.exposure_spread import exposure_spread
29
+ from global_func.reassess_edge import reassess_edge
30
 
31
  freq_format = {'Finish_percentile': '{:.2%}', 'Lineup Edge': '{:.2%}', 'Win%': '{:.2%}'}
32
  stacking_sports = ['MLB', 'NHL', 'NFL', 'LOL']
 
1527
  st.session_state['export_base']['salary'] = st.session_state['export_base']['salary'].astype('uint16')
1528
 
1529
  print(st.session_state['export_base'].head(10))
1530
+ st.session_state['export_base'] = reassess_edge(st.session_state['export_base'], st.session_state['export_base'], st.session_state['map_dict'], site_var, type_var, Contest_Size, strength_var, sport_var, salary_max)
1531
  st.session_state['export_merge'] = st.session_state['export_base'].copy()
1532
 
1533
  with st.container():
global_func/reassess_edge.py CHANGED
@@ -9,9 +9,62 @@ import pandas as pd
9
  import numpy as np
10
  import math
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def reassess_dupes(row: pd.Series, salary_max: int) -> float:
13
  return math.ceil(row['Dupes'] + ((row['salary_diff'] / 100) + ((salary_max + (salary_max - row['salary'])) / 100)) * (1 - (row['own_diff'] / 100))).clip(lower=0)
14
 
 
 
 
 
 
 
15
  def reassess_edge(refactored_frame: pd.DataFrame, original_frame: pd.DataFrame, maps_dict: dict, site_var: str, type_var: str, Contest_Size: int, strength_var: str, sport_var: str, salary_max: int) -> pd.DataFrame:
16
  orig_df = original_frame.copy()
17
  orig_df = orig_df.reset_index(drop=True)
@@ -24,12 +77,15 @@ def reassess_edge(refactored_frame: pd.DataFrame, original_frame: pd.DataFrame,
24
 
25
  change_mask = refactored_df[refactored_df['salary_diff'] != 0 | refactored_df['median_diff'] != 0 | refactored_df['own_diff'] != 0]
26
 
 
 
 
27
  for lineups in change_mask.index:
28
  refactored_df.loc[lineups, 'Dupes'] = reassess_dupes(refactored_df.loc[lineups, :], salary_max)
29
- refactored_df.loc[lineups, 'Finish_percentile'] = refactored_df.loc[lineups, 'Finish_percentile'] + 1
30
- refactored_df.loc[lineups, 'Win%'] = refactored_df.loc[lineups, 'Win%'] + 1
31
- refactored_df.loc[lineups, 'Edge'] = refactored_df.loc[lineups, 'Edge'] + 1
32
- refactored_df.loc[lineups, 'Weighted Own'] = refactored_df.loc[lineups, 'Weighted Own'] + 1
33
- refactored_df.loc[lineups, 'Geomean'] = refactored_df.loc[lineups, 'Geomean'] + 1
34
 
35
  return refactored_df
 
9
  import numpy as np
10
  import math
11
 
12
+ def calculate_weighted_ownership_vectorized(ownership_array):
13
+ """
14
+ Vectorized version of calculate_weighted_ownership using NumPy operations.
15
+
16
+ Args:
17
+ ownership_array: 2D array of ownership values (rows x players)
18
+
19
+ Returns:
20
+ array: Calculated weighted ownership values for each row
21
+ """
22
+ # Convert percentages to decimals and handle NaN values
23
+ ownership_array = np.where(np.isnan(ownership_array), 0, ownership_array) / 100
24
+
25
+ # Calculate row means
26
+ row_means = np.mean(ownership_array, axis=1, keepdims=True)
27
+
28
+ # Calculate average of each value with the overall mean
29
+ value_means = (ownership_array + row_means) / 2
30
+
31
+ # Take average of all those means
32
+ avg_of_means = np.mean(value_means, axis=1)
33
+
34
+ # Multiply by count of values
35
+ weighted = avg_of_means * ownership_array.shape[1]
36
+
37
+ # Subtract (max - min) for each row
38
+ row_max = np.max(ownership_array, axis=1)
39
+ row_min = np.min(ownership_array, axis=1)
40
+ weighted = weighted - (row_max - row_min)
41
+
42
+ # Convert back to percentage form
43
+ return weighted * 10000
44
+
45
+ def calculate_weighted_ownership_wrapper(row_ownerships):
46
+ """
47
+ Wrapper function for the original calculate_weighted_ownership to work with Pandas .apply()
48
+
49
+ Args:
50
+ row_ownerships: Series containing ownership values in percentage form
51
+
52
+ Returns:
53
+ float: Calculated weighted ownership value
54
+ """
55
+ # Convert Series to 2D array for vectorized function
56
+ ownership_array = row_ownerships.values.reshape(1, -1)
57
+ return calculate_weighted_ownership_vectorized(ownership_array)[0]
58
+
59
  def reassess_dupes(row: pd.Series, salary_max: int) -> float:
60
  return math.ceil(row['Dupes'] + ((row['salary_diff'] / 100) + ((salary_max + (salary_max - row['salary'])) / 100)) * (1 - (row['own_diff'] / 100))).clip(lower=0)
61
 
62
+ def reassess_edge(row: pd.Series, Contest_Size: int) -> float:
63
+ row['Lineup Edge'] = row['Win%'] * ((.5 - row['Finish_percentile']) * (Contest_Size / 2.5))
64
+ row['Lineup Edge'] = row.apply(lambda row: row['Lineup Edge'] / (row['Dupes'] + 1) if row['Dupes'] > 0 else row['Lineup Edge'], axis=1)
65
+
66
+ return row['Lineup Edge'] - row['Lineup Edge'].mean()
67
+
68
  def reassess_edge(refactored_frame: pd.DataFrame, original_frame: pd.DataFrame, maps_dict: dict, site_var: str, type_var: str, Contest_Size: int, strength_var: str, sport_var: str, salary_max: int) -> pd.DataFrame:
69
  orig_df = original_frame.copy()
70
  orig_df = orig_df.reset_index(drop=True)
 
77
 
78
  change_mask = refactored_df[refactored_df['salary_diff'] != 0 | refactored_df['median_diff'] != 0 | refactored_df['own_diff'] != 0]
79
 
80
+ num_players = len([col for col in refactored_df.columns if col not in ['salary', 'median', 'Own', 'Finish_percentile', 'Win%', 'Edge', 'Weighted Own', 'Geomean', 'salary_diff', 'median_diff', 'own_diff']])
81
+ own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
82
+
83
  for lineups in change_mask.index:
84
  refactored_df.loc[lineups, 'Dupes'] = reassess_dupes(refactored_df.loc[lineups, :], salary_max)
85
+ refactored_df.loc[lineups, 'Finish_percentile'] = refactored_df.loc[lineups, 'Finish_percentile']
86
+ refactored_df.loc[lineups, 'Win%'] = refactored_df.loc[lineups, 'Win%']
87
+ refactored_df.loc[lineups, 'Edge'] = reassess_edge(refactored_df.loc[lineups, :], Contest_Size)
88
+ refactored_df.loc[lineups, 'Weighted Own'] = refactored_df[own_columns].apply(calculate_weighted_ownership_wrapper, axis=1)
89
+ refactored_df.loc[lineups, 'Geomean'] = np.power((refactored_df.loc[lineups, own_columns] * 100).product(axis=1), 1 / len(own_columns))
90
 
91
  return refactored_df