Created
July 4, 2025 02:15
-
-
Save micahmelling/44c760da26d4a50fb95b84cc7fd3764c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pandas as pd | |
| from scipy.stats import norm | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| np.random.seed(42) | |
| pd.set_option('display.max_rows', None) | |
| pd.set_option('display.max_columns', None) | |
| pd.set_option('display.width', None) | |
| df = pd.DataFrame({ | |
| "player": [ | |
| "Salvador Perez", | |
| "Vinnie Pasquantino", | |
| "Bobby Witt Jr", | |
| "Maikel Garcia", | |
| "Jonathan India", | |
| "Kyle Isbel", | |
| "Drew Waters", | |
| "Michael Massey", | |
| "Freddy Fermin", | |
| ], | |
| "actual_ops": [ | |
| 656, | |
| 738, | |
| 825, | |
| 846, | |
| 664, | |
| 642, | |
| 615, | |
| 479, | |
| 654 | |
| ], | |
| "ops_expectation": [ | |
| 740, | |
| 760, | |
| 925, | |
| 700, | |
| 740, | |
| 650, | |
| 625, | |
| 700, | |
| 675 | |
| ], | |
| "ops_std": [ | |
| 60, | |
| 60, | |
| 50, | |
| 50, | |
| 50, | |
| 40, | |
| 40, | |
| 40, | |
| 40 | |
| ] | |
| }) | |
| def get_prob_less_than_or_equal(mean, std_dev, val): | |
| return norm.cdf(val, loc=mean, scale=std_dev) | |
| for index, row in df.iterrows(): | |
| prob = get_prob_less_than_or_equal(row['ops_expectation'], row['ops_std'], row['actual_ops']) | |
| df.loc[index, 'prob'] = prob | |
| random_values = np.random.normal(loc=row['ops_expectation'], scale=row['ops_std'], size=100) | |
| random_values = [int(i) for i in random_values] | |
| for i, v in enumerate(random_values): | |
| prob = get_prob_less_than_or_equal(row['ops_expectation'], row['ops_std'], v) | |
| df.loc[index, f'prob_{i}'] = prob | |
| df = df.set_index(keys=["player"]) | |
| df = df.round(3) | |
| df.loc['mean'] = df.mean() | |
| df = df.reset_index(drop=False) | |
| print(df) | |
| print() | |
| df.to_csv('data.csv', index=False) | |
| plot_df = df.tail(1).drop(labels=['player', 'actual_ops', 'ops_expectation', 'ops_std'], axis=1) | |
| x = range(len(plot_df.columns)) | |
| y = plot_df.iloc[0] | |
| plt.scatter(x[0], y[0], color='red', label='2025 actual') | |
| plt.scatter(x[1:], y[1:], color='blue') | |
| plt.axhline(y.mean(), color='green', linestyle='--', label='Average') | |
| plt.yticks([0, 0.25, 0.50, 0.75, 1]) | |
| plt.xlabel('simulation run #') | |
| plt.ylabel('average player probability') | |
| plt.legend() | |
| plt.title('Average Probability of Player OPS Ceiling') | |
| plt.savefig('royals_sim_prob.png') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment