UFCData 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UFCData
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Obtain UFC data and functions to manipulate it
5
5
  Requires-Python: >=3.10
6
6
  License-File: LICENSE.md
@@ -9,4 +9,5 @@ Requires-Dist: pandas
9
9
  Requires-Dist: numpy
10
10
  Requires-Dist: glicko2
11
11
  Requires-Dist: rapidfuzz
12
+ Requires-Dist: matplotlib
12
13
  Dynamic: license-file
@@ -4,8 +4,6 @@ An open-source Python package for accessing, manipulating, and analyzing UFC dat
4
4
 
5
5
  https://pypi.org/project/UFCData/
6
6
 
7
- add helper functions like convert odds
8
-
9
7
  ## Table of Contents
10
8
 
11
9
  - [Installation](#installation)
@@ -29,7 +27,11 @@ Helper Functions
29
27
  - [Mirror](#mirror)
30
28
 
31
29
  Model Evaluation
32
- - [Odds Baseline Example](#elo)
30
+ - [Train Test Split](#train-test-split)
31
+ - [Get Expanding Window](#get-expanding-window)
32
+ - [Plotting Accuracy](#plotting-accuracy)
33
+ - [Expanding Window Baseline Example](#expanding-window-cv-and-final-test-example)
34
+
33
35
 
34
36
  Data Sources
35
37
  - [Online Sources](#online-sources)
@@ -100,7 +102,7 @@ This is useful when the exact value stored in the dataset is unknown or when the
100
102
 
101
103
  ## Elo
102
104
 
103
- UFCData provides an Elo rating system for calculating fighter ratings based on their previous fight results. Ratings are calculated chronologically, with each fighter's rating recorded **immediately before each fight**.
105
+ UFCData provides an Elo rating system for calculating fighter ratings based on their previous fight results. Ratings are calculated chronologically, with each fighter's rating recorded immediately before each fight.
104
106
 
105
107
  This allows Elo ratings to be used as features for predictive modeling without incorporating information from the fight being predicted.
106
108
 
@@ -146,7 +148,7 @@ The resulting `fight_elo` dataframe can then be used to examine or incorporate p
146
148
 
147
149
  ### Important
148
150
 
149
- `fight_df` should be sorted from **most recent to least recent** before being passed to `get_elo()`. The function reverses the dataframe internally to process fights chronologically and returns the resulting data in the original order.
151
+ `fight_df` should be sorted from most recent to least recent before being passed to `get_elo()`. The function reverses the dataframe internally to process fights chronologically and returns the resulting data in the original order.
150
152
 
151
153
  ## Fighter History
152
154
 
@@ -181,14 +183,12 @@ data = ufc.get_data()
181
183
  fighter_bio = data["fighter_bio"].copy()
182
184
  fights_df = data["past_fights"].copy()
183
185
 
184
- # Obtain Jon Jones' UFCStats link
185
186
  jon_jones = ufc.search(
186
187
  fighter_bio,
187
188
  "Name",
188
189
  "Jon Jones"
189
190
  ).iloc[0]["Fighter Link"]
190
191
 
191
- # Get Jon Jones' fight history
192
192
  jon_jones_history = ufc.get_fighter_history(
193
193
  jon_jones,
194
194
  fighter_bio,
@@ -201,7 +201,7 @@ This function is useful for analyzing an individual fighter's career, constructi
201
201
  ## Fighter Statistic
202
202
 
203
203
 
204
- The function `get_fighter_statistic()`, transforms a fighter's UFC fight history into a time-series dataset where each row represents the fighter's statistics **as they were known before a particular fight**.
204
+ The function `get_fighter_statistic()`, transforms a fighter's UFC fight history into a time-series dataset where each row represents the fighter's statistics as they were known before a particular fight.
205
205
 
206
206
  This is designed for machine-learning applications where using information from the future would cause data leakage.
207
207
 
@@ -265,7 +265,7 @@ This includes:
265
265
 
266
266
  A DataFrame containing the same types of statistics for each previous UFC fight.
267
267
 
268
- Each row represents the fighter's information **immediately before that fight**.
268
+ Each row represents the fighter's information immediately before that fight.
269
269
 
270
270
  For example:
271
271
 
@@ -291,14 +291,12 @@ fights_df = data["past_fights"].copy()
291
291
  rounds_df = data['past_rounds'].copy()
292
292
  future_df = data['future_fights']
293
293
 
294
- # Obtain Jon Jones' UFCStats link
295
294
  jon_jones = ufc.search(
296
295
  fighter_bio,
297
296
  "Name",
298
297
  "Jon Jones"
299
298
  ).iloc[0]["Fighter Link"]
300
299
 
301
- # Get Jon Jones' statistic
302
300
  jon_jones_current, jon_jones_past = ufc.get_fighter_statistic(
303
301
  jon_jones,
304
302
  fighter_bio,
@@ -496,6 +494,106 @@ Mirrored Fight 2
496
494
 
497
495
  This is useful when creating fighter-level datasets where each fight should be represented from both fighters' perspectives.
498
496
 
497
+ ## Train Test Split
498
+ The function `train_test_split()` splits a UFC fight DataFrame into training and test sets while preserving the chronological order of the data. Unlike `sklearn.model_selection.train_test_split()`, this function does not randomly shuffle the data.
499
+
500
+ The input `fights_df` should be ordered from newest to oldest. The most recent fights are assigned to the test set, while the older fights are assigned to the training set. Both returned DataFrames are then reordered from oldest to newest.
501
+
502
+ ```python
503
+ train_test_split(fights_df, test_size=0.2)
504
+ ```
505
+ ### Parameters
506
+
507
+ * `fights_df` — UFC fight DataFrame ordered from newest to oldest.
508
+ * `test_size` — Determines the size of the test set. If less than 1, it is interpreted as a proportion of the total number of fights. If greater than or equal to 1, it is interpreted as the exact number of fights to include in the test set. Defaults to 0.2.
509
+ ### Returns
510
+ The function returns two dataFrames. The first is a dataFrame containing the older fights used for training, ordered from oldest to newest. The second is a dataFrame containing the most recent fights used for testing, ordered from oldest to newest.
511
+
512
+ ### Example
513
+
514
+ ```python
515
+ import ufcdata as ufc
516
+
517
+ data = ufc.get_data()
518
+
519
+ past_fights = data["past_fights"].copy()
520
+ train, test = ufc.train_test_split(past_fights, 0.2)
521
+ train
522
+ ```
523
+
524
+ ## Get Expanding Window
525
+ The function `get_expanding_window()` creates multiple training and test sets for time-series cross-validation using an expanding training window.
526
+
527
+ The input `fights_df` should be ordered from oldest to newest. With each fold, the training set expands to include more historical fights, while the test set remains a fixed size.
528
+
529
+ ```python
530
+ fold_results = ufc.get_expanding_window(
531
+ fights_df,
532
+ folds=5,
533
+ test_size=500
534
+ )
535
+ ```
536
+ ### Parameters
537
+
538
+ * `fights_df` — UFC fight DataFrame ordered from oldest to newest.
539
+ * `folds` — The number of train/test folds to create.
540
+ * `test_size` — The number of fights included in each test set.
541
+
542
+ ### Returns
543
+ The function returns a dictionary containing the training and test DataFrames for each fold.
544
+ ```python
545
+ {
546
+ "Fold 1": {
547
+ "train": train_dataframe,
548
+ "test": test_dataframe
549
+ },
550
+ "Fold 2": {
551
+ "train": train_dataframe,
552
+ "test": test_dataframe
553
+ },
554
+ ...
555
+ }
556
+ ```
557
+ ### Example
558
+
559
+ ```python
560
+ import ufcdata as ufc
561
+
562
+ data = ufc.get_data()
563
+
564
+ past_fights = data["past_fights"].copy()
565
+ train, test = ufc.train_test_split(past_fights, 0.2)
566
+
567
+ folds = ufc.get_expanding_window(train, 10, 500)
568
+ folds['Fold 2']['test']
569
+ ```
570
+
571
+ ## Plotting Accuracy
572
+
573
+ The function `plot_cv` plots out a line graph showing the accuracy of each fold along with a line showing the mean.
574
+
575
+ ```python
576
+ plot_cv(cv_labels, cv_accuracies, title="Cross Validation Accuracy")
577
+ ```
578
+
579
+ ### Parameters
580
+
581
+ * `cv_labels` — The list of fold names.
582
+ * `cv_accuracies` — The list of accuracies.
583
+ * `title` — The title of the plot.
584
+
585
+ The function `plot_test` plots out a single bar graph showing the accuracy of a single test.
586
+
587
+ ```python
588
+ plot_test(accuracy, title="Test Accuracy")
589
+ ```
590
+
591
+ ### Parameters
592
+
593
+ * `accuracy` — The accuracy.
594
+ * `title` — The title of the plot.
595
+
596
+ ## Expanding Window Baseline Example
499
597
 
500
598
  ## Online Sources
501
599
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UFCData
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Obtain UFC data and functions to manipulate it
5
5
  Requires-Python: >=3.10
6
6
  License-File: LICENSE.md
@@ -9,4 +9,5 @@ Requires-Dist: pandas
9
9
  Requires-Dist: numpy
10
10
  Requires-Dist: glicko2
11
11
  Requires-Dist: rapidfuzz
12
+ Requires-Dist: matplotlib
12
13
  Dynamic: license-file
@@ -3,3 +3,4 @@ pandas
3
3
  numpy
4
4
  glicko2
5
5
  rapidfuzz
6
+ matplotlib
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "UFCData"
3
- version = "0.6.0"
3
+ version = "0.7.0"
4
4
  description = "Obtain UFC data and functions to manipulate it"
5
5
  requires-python = ">=3.10"
6
6
 
@@ -10,4 +10,5 @@ dependencies = [
10
10
  "numpy",
11
11
  "glicko2",
12
12
  "rapidfuzz",
13
+ "matplotlib",
13
14
  ]
@@ -3,4 +3,4 @@ from .search import search
3
3
  from .ratings import get_elo
4
4
  from .fighter import get_fighter_history, get_fighter_statistic
5
5
  from .helper import convert_odds, convert_gender, convert_weight, mirror
6
- from .evaluation import train_test_split, get_expanding_window
6
+ from .evaluation import train_test_split, get_expanding_window, plot_cv, plot_test
@@ -1,4 +1,5 @@
1
1
  import numpy as np
2
+ import matplotlib.pyplot as plt
2
3
 
3
4
  def train_test_split(fights_df, test_size=0.2):
4
5
  """
@@ -117,4 +118,75 @@ def get_expanding_window(fights_df, folds, test_size):
117
118
  "test": test
118
119
  }
119
120
 
120
- return fold_results
121
+ return fold_results
122
+
123
+ def plot_cv(cv_labels, cv_accuracies, title="Cross Validation Accuracy"):
124
+ plt.figure(figsize=(10, 5))
125
+
126
+ plt.plot(
127
+ cv_labels,
128
+ cv_accuracies,
129
+ color="#666666",
130
+ linestyle="-",
131
+ linewidth=2,
132
+ marker="o",
133
+ markersize=7,
134
+ markerfacecolor="#D20A0A", # UFC red dots
135
+ markeredgecolor="#FFFFFF",
136
+ markeredgewidth=1.5,
137
+ label="Fold Accuracy"
138
+ )
139
+
140
+
141
+ # Mean accuracy across folds
142
+ mean_accuracy = np.mean(cv_accuracies)
143
+
144
+ plt.axhline(
145
+ mean_accuracy,
146
+ color="#D20A0A",
147
+ linestyle="--",
148
+ linewidth=2,
149
+ label=f"Mean Accuracy: {mean_accuracy:.1%}"
150
+ )
151
+
152
+
153
+ plt.xlabel("Fold")
154
+ plt.ylabel("Accuracy")
155
+ plt.title(title)
156
+ # plt.ylim(0, 1)
157
+
158
+ plt.xticks(rotation=45)
159
+ plt.grid(True, alpha=0.3)
160
+ plt.legend()
161
+
162
+ plt.tight_layout()
163
+ plt.show()
164
+
165
+ def plot_test(accuracy, title="Test Accuracy"):
166
+ plt.figure(figsize=(6, 5))
167
+
168
+ plt.bar(
169
+ 0,
170
+ accuracy,
171
+ color="#D20A0A",
172
+ width=0.25
173
+ )
174
+
175
+ plt.ylabel("Accuracy")
176
+ plt.title(title)
177
+ plt.ylim(0, 1)
178
+
179
+ plt.xlim(-0.5, 0.5)
180
+ plt.xticks([0], ["Test Set"])
181
+
182
+ plt.text(
183
+ 0,
184
+ accuracy + 0.02,
185
+ f"{accuracy:.1%}",
186
+ ha="center",
187
+ fontweight="bold",
188
+ color="#444444"
189
+ )
190
+
191
+ plt.tight_layout()
192
+ plt.show()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes