cfbd_json_py.metrics

   1# Creation Date: 08/30/2023 01:13 EDT
   2# Last Updated Date: 09/16/2024 06:10 PM EDT
   3# Author: Joseph Armstrong (armstrongjoseph08@gmail.com)
   4# File Name: metrics.py
   5# Purpose: Houses functions pertaining to various CFB
   6#    stats within the CFBD API.
   7###############################################################################
   8
   9import logging
  10from datetime import datetime
  11
  12import pandas as pd
  13import requests
  14
  15from cfbd_json_py.utls import get_cfbd_api_token
  16
  17
  18def get_cfbd_predicted_ppa_from_down_distance(
  19    down: int,
  20    distance: int,
  21    api_key: str = None,
  22    api_key_dir: str = None,
  23    return_as_dict: bool = False,
  24):
  25    """
  26    Given a down and distance,
  27    this function will attempt to get the predicted
  28    PPA value for that down and distance,
  29    at every yard line possible for that down and distance.
  30
  31    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
  32
  33    For this endpoint,
  34    [`yardLine`] is the number of yards from 1
  35    (offense has the ball on their side,at their 1 yard line),
  36    to 99 (offense with the ball with a X and goal situation
  37    on the opponent's 1 yard line.
  38
  39    Parameters
  40    ----------
  41    `down` (int, mandatory):
  42        Mandatory argument.
  43        This is the down (a number between 1 and 4 in normal situations)
  44        for this play you want PPA for.
  45
  46    `distance` (int, mandatory):
  47        Mandatory argument.
  48        This variable should be set to the number of yards between
  49        the line of scrimmage (LOS), and the first down line on the field.
  50
  51    `api_key` (str, optional):
  52        Semi-optional argument.
  53        If `api_key` is null, this function will attempt to load a CFBD API key
  54        from the python environment, or from a file on this computer.
  55        If `api_key` is not null,
  56        this function will automatically assume that the
  57        inputted `api_key` is a valid CFBD API key.
  58
  59    `api_key_dir` (str, optional):
  60        Optional argument.
  61        If `api_key` is set to am empty string, this variable is ignored.
  62        If `api_key_dir` is null, and `api_key` is null,
  63        this function will try to find
  64        a CFBD API key file in this user's home directory.
  65        If `api_key_dir` is set to a string, and `api_key` is null,
  66        this function will assume that `api_key_dir` is a directory,
  67        and will try to find a CFBD API key file in that directory.
  68
  69    `return_as_dict` (bool, semi-optional):
  70        Semi-optional argument.
  71        If you want this function to return the data as a dictionary
  72        (read: JSON object), instead of a pandas `DataFrame` object,
  73        set `return_as_dict` to `True`.
  74
  75    Usage
  76    ----------
  77    ```
  78    import time
  79
  80    from cfbd_json_py.metrics import get_cfbd_predicted_ppa_from_down_distance
  81
  82
  83    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
  84
  85    if cfbd_key != "tigersAreAwesome":
  86        print(
  87            "Using the user's API key declared " +
  88            "in this script for this example."
  89        )
  90
  91        # Get the predicted PPA for a 1st and 10 play,
  92        # in every possible situation.
  93        print(
  94            "Get the predicted PPA for a 1st and 10 play, " +
  95            "in every possible situation."
  96        )
  97        json_data = get_cfbd_predicted_ppa_from_down_distance(
  98            down=1,
  99            distance=10,
 100            api_key=cfbd_key
 101        )
 102        print(json_data)
 103        time.sleep(5)
 104
 105
 106        # You can also tell this function to just return the API call as
 107        # a Dictionary (read: JSON) object.
 108        print(
 109            "You can also tell this function to just return the API call " +
 110            "as a Dictionary (read: JSON) object."
 111        )
 112        json_data = get_cfbd_predicted_ppa_from_down_distance(
 113            down=1,
 114            distance=10,
 115            api_key=cfbd_key,
 116            return_as_dict=True
 117        )
 118        print(json_data)
 119
 120    else:
 121        # Alternatively, if the CFBD API key exists in this python environment,
 122        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
 123        # you could just call these functions directly,
 124        # without setting the API key in the script.
 125        print(
 126            "Using the user's API key supposedly loaded " +
 127            "into this python environment for this example."
 128        )
 129
 130
 131        # Get the predicted PPA for a 1st and 10 play,
 132        # in every possible situation.
 133        print(
 134            "Get the predicted PPA for a 1st and 10 play, " +
 135            "in every possible situation."
 136        )
 137        json_data = get_cfbd_predicted_ppa_from_down_distance(
 138            down=1,
 139            distance=10
 140        )
 141        print(json_data)
 142        time.sleep(5)
 143
 144
 145        # You can also tell this function to just return the API call as
 146        # a Dictionary (read: JSON) object.
 147        print(
 148            "You can also tell this function to just return the API call " +
 149            "as a Dictionary (read: JSON) object."
 150        )
 151        json_data = get_cfbd_predicted_ppa_from_down_distance(
 152            down=1,
 153            distance=10,
 154            return_as_dict=True
 155        )
 156        print(json_data)
 157
 158    ```
 159    Returns
 160    ----------
 161    A pandas `DataFrame` object with a calculated PPA from a down and distance,
 162    or (if `return_as_dict` is set to `True`)
 163    a dictionary object with a calculated PPA from a down and distance.
 164
 165
 166    """
 167
 168    ppa_df = pd.DataFrame()
 169    url = "https://api.collegefootballdata.com/ppa/predicted"
 170
 171    ##########################################################################
 172
 173    if api_key is not None:
 174        real_api_key = api_key
 175        del api_key
 176    else:
 177        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
 178
 179    if real_api_key == "tigersAreAwesome":
 180        raise ValueError(
 181            "You actually need to change `cfbd_key` to your CFBD API key."
 182        )
 183    elif "Bearer " in real_api_key:
 184        pass
 185    elif "Bearer" in real_api_key:
 186        real_api_key = real_api_key.replace("Bearer", "Bearer ")
 187    else:
 188        real_api_key = "Bearer " + real_api_key
 189
 190    if down >= 1 and down <= 4:
 191        # This is normal, so pass.
 192        pass
 193    elif down == 5:
 194        # Due to a Missouri-Colorado game in the 90s
 195        # being won by Colorado on a mythical "5th down",
 196        # we cannot reject this down outright,
 197        # but we have to convey to the person calling this
 198        # function that setting `down = 5`
 199        # is not something they should be doing.
 200        logging.warning(
 201            'There is a very limited number of "5th down" situations '
 202            + "in American Football history. "
 203            + "Do not expect anything back when calling this function, "
 204            + "and setting`down` to `5`."
 205        )
 206    else:
 207        raise ValueError(
 208            "Invalid `down` inputted! Valid inputs are:\n"
 209            + "\n\t- `1`"
 210            + "\n\t- `2`"
 211            + "\n\t- `3`"
 212            + "\n\t- `4`"
 213            + f"\nYou entered: \t`{down}`"
 214        )
 215
 216    if distance == 0:
 217        raise ValueError(
 218            'If you want "X and inches" predicted PPA data, '
 219            + "set `down` to `1` when calling this function."
 220        )
 221    elif distance >= 100 and distance <= 110:
 222        raise ValueError(
 223            "The CFBD API cannot calculate predicted PPA for "
 224            + "U-Sports (Canada) football."
 225        )
 226    elif distance >= 1 and distance <= 99:
 227        # While numbers beyond 30 are rare,
 228        # there are some situations IRL that caused the distance
 229        # in "down and distance" to exceed 90
 230        # (most famously a 2017 game between
 231        # Mississippi State and Louisiana Tech).
 232        pass
 233
 234    # URL builder
 235    ##########################################################################
 236
 237    # Required by API
 238    url += f"?down={down}&distance={distance}"
 239
 240    headers = {
 241        "Authorization": f"{real_api_key}", "accept": "application/json"
 242    }
 243
 244    response = requests.get(url, headers=headers)
 245
 246    if response.status_code == 200:
 247        pass
 248    elif response.status_code == 401:
 249        raise ConnectionRefusedError(
 250            "Could not connect. The connection was refused.\n" +
 251            "HTTP Status Code 401."
 252        )
 253    else:
 254        raise ConnectionError(
 255            f"Could not connect.\nHTTP Status code {response.status_code}"
 256        )
 257
 258    json_data = response.json()
 259
 260    if return_as_dict is True:
 261        return json_data
 262
 263    ppa_df = pd.json_normalize(json_data)
 264    ppa_df.rename(
 265        columns={
 266            "yardLine": "yard_line",
 267            "predictedPoints": "predicted_points"
 268        },
 269        inplace=True,
 270    )
 271    return ppa_df
 272
 273
 274def get_cfbd_team_season_ppa_data(
 275    api_key: str = None,
 276    api_key_dir: str = None,
 277    season: int = None,
 278    team: str = None,
 279    # `year` and/or `team` must be not null for this function to work.
 280    conference: str = None,
 281    exclude_garbage_time: bool = False,
 282    return_as_dict: bool = False,
 283):
 284    """
 285    Allows you to get team PPA data,
 286    over an entire season,
 287    with or without garbage time plays,
 288    for a specified team and/or time period.
 289
 290    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
 291
 292    Parameters
 293    ----------
 294    `api_key` (str, optional):
 295        Semi-optional argument.
 296        If `api_key` is null, this function will attempt to load a CFBD API key
 297        from the python environment, or from a file on this computer.
 298        If `api_key` is not null,
 299        this function will automatically assume that the
 300        inputted `api_key` is a valid CFBD API key.
 301
 302    `api_key_dir` (str, optional):
 303        Optional argument.
 304        If `api_key` is set to am empty string, this variable is ignored.
 305        If `api_key_dir` is null, and `api_key` is null,
 306        this function will try to find
 307        a CFBD API key file in this user's home directory.
 308        If `api_key_dir` is set to a string, and `api_key` is null,
 309        this function will assume that `api_key_dir` is a directory,
 310        and will try to find a CFBD API key file in that directory.
 311
 312    `season` (int, optional):
 313        Semi-optional argument.
 314        Specifies the season you want team PPA data from.
 315        You MUST set `season` or `team` to a non-null value for
 316        this function to work. If you don't, a `ValueError()`
 317        will be raised.
 318
 319    `team` (str, optional):
 320        Semi-optional argument.
 321        If you only want team PPA data for a specific team,
 322        set `team` to the name of the team you want team PPA data from.
 323        You MUST set `season` or `team` to a non-null value for
 324        this function to work. If you don't, a `ValueError()`
 325        will be raised.
 326
 327    `conference` (str, optional):
 328        Optional argument.
 329        If you only want team PPA data from games
 330        involving teams from a specific conference,
 331        set `conference` to the abbreviation
 332        of the conference you want team PPA data from.
 333        For a list of conferences,
 334        use the `cfbd_json_py.conferences.get_cfbd_conference_info()`
 335        function.
 336
 337    `exclude_garbage_time` (bool, optional):
 338        Optional argument.
 339        If you want to filter out plays
 340        where the result of the game is largely decided,
 341        set `exclude_garbage_time = True`.
 342        Default behavior is that this variable is set to
 343        `False` when this function is called.
 344
 345    `return_as_dict` (bool, semi-optional):
 346        Semi-optional argument.
 347        If you want this function
 348        to return the data as a dictionary (read: JSON object),
 349        instead of a pandas `DataFrame` object,
 350        set `return_as_dict` to `True`.
 351
 352    Usage
 353    ----------
 354    ```
 355    import time
 356
 357    from cfbd_json_py.metrics import get_cfbd_team_season_ppa_data
 358
 359
 360    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
 361
 362    if cfbd_key != "tigersAreAwesome":
 363        print(
 364            "Using the user's API key declared in this script " +
 365            "for this example."
 366        )
 367
 368        # Get team season PPA data for the 2020 CFB season.
 369        print("Get team PPA data for the 2020 CFB season.")
 370        json_data = get_cfbd_team_season_ppa_data(
 371            api_key=cfbd_key,
 372            season=2020
 373        )
 374        print(json_data)
 375        time.sleep(5)
 376
 377        # Get team season PPA data for the 2020 Ohio State Buckeyes.
 378        print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
 379        json_data = get_cfbd_team_season_ppa_data(
 380            api_key=cfbd_key,
 381            season=2020,
 382            team="Ohio State"
 383        )
 384        print(json_data)
 385        time.sleep(5)
 386
 387        # Get team season PPA data for the 2020 Ohio State Buckeyes,
 388        # but exclude garbage time plays when making the PPA calculations.
 389        print(
 390            "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
 391            "but exclude garbage time plays when making the PPA calculations."
 392        )
 393        json_data = get_cfbd_team_season_ppa_data(
 394            api_key=cfbd_key,
 395            season=2020,
 396            team="Ohio State",
 397            exclude_garbage_time=True
 398        )
 399        print(json_data)
 400        time.sleep(5)
 401
 402        # Get team season PPA data for teams in the Big 10 (B1G) Conference
 403        # in the 2020 CFB Season.
 404        print(
 405            "Get team season PPA data for teams in the " +
 406            "Big 10 (B1G) Conference in the 2020 CFB Season."
 407        )
 408        json_data = get_cfbd_team_season_ppa_data(
 409            api_key=cfbd_key,
 410            season=2020,
 411            conference="B1G"
 412        )
 413        print(json_data)
 414        time.sleep(5)
 415
 416        # You can also tell this function to just return the API call as
 417        # a Dictionary (read: JSON) object.
 418        print(
 419            "You can also tell this function to just return the API call " +
 420            "as a Dictionary (read: JSON) object."
 421        )
 422        json_data = get_cfbd_team_season_ppa_data(
 423            api_key=cfbd_key,
 424            season=2020,
 425            conference="B1G",
 426            return_as_dict=True
 427        )
 428        print(json_data)
 429
 430    else:
 431        # Alternatively, if the CFBD API key exists in this python environment,
 432        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
 433        # you could just call these functions directly,
 434        # without setting the API key in the script.
 435        print(
 436            "Using the user's API key supposedly loaded into " +
 437            "this python environment for this example."
 438        )
 439
 440        # Get team season PPA data for the 2020 CFB season.
 441        print("Get team PPA data for the 2020 CFB season.")
 442        json_data = get_cfbd_team_season_ppa_data(
 443            season=2020
 444        )
 445        print(json_data)
 446        time.sleep(5)
 447
 448        # Get team season PPA data for the 2020 Ohio State Buckeyes.
 449        print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
 450        json_data = get_cfbd_team_season_ppa_data(
 451            season=2020,
 452            team="Ohio State"
 453        )
 454        print(json_data)
 455        time.sleep(5)
 456
 457        # Get team season PPA data for the 2020 Ohio State Buckeyes,
 458        # but exclude garbage time plays when making the PPA calculations.
 459        print(
 460            "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
 461            "but exclude garbage time plays when making the PPA calculations."
 462        )
 463        json_data = get_cfbd_team_season_ppa_data(
 464            season=2020,
 465            team="Ohio State",
 466            exclude_garbage_time=True
 467        )
 468        print(json_data)
 469        time.sleep(5)
 470
 471        # Get team season PPA data for teams in
 472        # the Big 10 (B1G) Conference in the 2020 CFB Season.
 473        print(
 474            "Get team season PPA data for teams in " +
 475            "the Big 10 (B1G) Conference in the 2020 CFB Season."
 476        )
 477        json_data = get_cfbd_team_season_ppa_data(
 478            season=2020,
 479            conference="B1G"
 480        )
 481        print(json_data)
 482        time.sleep(5)
 483
 484        # You can also tell this function to just return the API call as
 485        # a Dictionary (read: JSON) object.
 486        print(
 487            "You can also tell this function to just return the API call " +
 488            "as a Dictionary (read: JSON) object."
 489        )
 490        json_data = get_cfbd_team_season_ppa_data(
 491            season=2020,
 492            conference="B1G",
 493            return_as_dict=True
 494        )
 495        print(json_data)
 496
 497    ```
 498    Returns
 499    ----------
 500    A pandas `DataFrame` object with team season PPA data,
 501    or (if `return_as_dict` is set to `True`)
 502    a dictionary object with a team season PPA data.
 503
 504    """
 505
 506    now = datetime.now()
 507    ppa_df = pd.DataFrame()
 508    # row_df = pd.DataFrame()
 509    url = "https://api.collegefootballdata.com/ppa/teams"
 510
 511    ##########################################################################
 512
 513    if api_key is not None:
 514        real_api_key = api_key
 515        del api_key
 516    else:
 517        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
 518
 519    if real_api_key == "tigersAreAwesome":
 520        raise ValueError(
 521            "You actually need to change `cfbd_key` to your CFBD API key."
 522        )
 523    elif "Bearer " in real_api_key:
 524        pass
 525    elif "Bearer" in real_api_key:
 526        real_api_key = real_api_key.replace("Bearer", "Bearer ")
 527    else:
 528        real_api_key = "Bearer " + real_api_key
 529
 530    if season is None and team is None:
 531        raise ValueError(
 532            "To use this function, `season` and/or `team` must be set to a "
 533            + "non-null variable."
 534        )
 535
 536    if season is None:
 537        # Rare, but in this endpoint,
 538        # you don't need to input the season.
 539        pass
 540    elif season > (now.year + 1):
 541        raise ValueError(f"`season` cannot be greater than {season}.")
 542    elif season < 1869:
 543        raise ValueError("`season` cannot be less than 1869.")
 544
 545    gt_str = ""
 546    if exclude_garbage_time is True:
 547        gt_str = "true"
 548    elif exclude_garbage_time is False:
 549        gt_str = "false"
 550
 551    # URL builder
 552    ##########################################################################
 553
 554    url_elements = 0
 555
 556    if season is not None and url_elements == 0:
 557        url += f"?year={season}"
 558        url_elements += 1
 559    elif season is not None:
 560        url += f"&year={season}"
 561        url_elements += 1
 562
 563    if team is not None and url_elements == 0:
 564        url += f"?team={team}"
 565        url_elements += 1
 566    elif team is not None:
 567        url += f"&team={team}"
 568        url_elements += 1
 569
 570    if conference is not None and url_elements == 0:
 571        url += f"?conference={conference}"
 572        url_elements += 1
 573    elif conference is not None:
 574        url += f"&conference={conference}"
 575        url_elements += 1
 576
 577    if exclude_garbage_time is not None and url_elements == 0:
 578        url += f"?excludeGarbageTime={gt_str}"
 579        url_elements += 1
 580    elif exclude_garbage_time is not None:
 581        url += f"&excludeGarbageTime={gt_str}"
 582        url_elements += 1
 583
 584    headers = {
 585        "Authorization": f"{real_api_key}", "accept": "application/json"
 586    }
 587
 588    response = requests.get(url, headers=headers)
 589
 590    if response.status_code == 200:
 591        pass
 592    elif response.status_code == 401:
 593        raise ConnectionRefusedError(
 594            "Could not connect. The connection was refused.\n" +
 595            "HTTP Status Code 401."
 596        )
 597    else:
 598        raise ConnectionError(
 599            f"Could not connect.\nHTTP Status code {response.status_code}"
 600        )
 601
 602    json_data = response.json()
 603
 604    if return_as_dict is True:
 605        return json_data
 606
 607    ppa_df = pd.json_normalize(json_data)
 608    # print(ppa_df.columns)
 609    ppa_df.rename(
 610        columns={
 611            "conference": "conference_name",
 612            "team": "team_name",
 613            "offense.overall": "ppa_offense_overall",
 614            "offense.passing": "ppa_offense_passing",
 615            "offense.rushing": "ppa_offense_rushing",
 616            "offense.firstDown": "ppa_offense_first_down",
 617            "offense.secondDown": "ppa_offense_second_down",
 618            "offense.thirdDown": "ppa_offense_third_down",
 619            "offense.cumulative.total": "ppa_offense_cumulative_total",
 620            "offense.cumulative.passing": "ppa_offense_cumulative_passing",
 621            "offense.cumulative.rushing": "ppa_offense_cumulative_rushing",
 622            "defense.overall": "ppa_defense_overall",
 623            "defense.passing": "ppa_defense_passing",
 624            "defense.rushing": "ppa_defense_rushing",
 625            "defense.firstDown": "ppa_defense_first_down",
 626            "defense.secondDown": "ppa_defense_second_down",
 627            "defense.thirdDown": "ppa_defense_third_down",
 628            "defense.cumulative.total": "ppa_defense_cumulative_total",
 629            "defense.cumulative.passing": "ppa_defense_cumulative_passing",
 630            "defense.cumulative.rushing": "ppa_defense_cumulative_rushing",
 631        },
 632        inplace=True,
 633    )
 634    return ppa_df
 635
 636
 637def get_cfbd_team_game_ppa_data(
 638    season: int,
 639    api_key: str = None,
 640    api_key_dir: str = None,
 641    week: int = None,
 642    team: str = None,
 643    conference: str = None,
 644    exclude_garbage_time: bool = False,
 645    season_type: str = "regular",  # "regular" or "postseason"
 646    return_as_dict: bool = False,
 647):
 648    """
 649    Allows you to get team PPA data,
 650    at a game level,
 651    with or without garbage time plays,
 652    for a specified team and/or time period.
 653
 654    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
 655
 656    Parameters
 657    ----------
 658    `season` (int, mandatory):
 659        Required argument.
 660        Specifies the season you want team game PPA data information from.
 661        This must be specified, otherwise this package, and by extension
 662        the CFBD API, will not accept the request
 663        to get team game PPA data information.
 664
 665    `api_key` (str, optional):
 666        Semi-optional argument.
 667        If `api_key` is null, this function will attempt to load a CFBD API key
 668        from the python environment, or from a file on this computer.
 669        If `api_key` is not null,
 670        this function will automatically assume that the
 671        inputted `api_key` is a valid CFBD API key.
 672
 673    `api_key_dir` (str, optional):
 674        Optional argument.
 675        If `api_key` is set to am empty string, this variable is ignored.
 676        If `api_key_dir` is null, and `api_key` is null,
 677        this function will try to find
 678        a CFBD API key file in this user's home directory.
 679        If `api_key_dir` is set to a string, and `api_key` is null,
 680        this function will assume that `api_key_dir` is a directory,
 681        and will try to find a CFBD API key file in that directory.
 682
 683    `week` (int, optional):
 684        Optional argument.
 685        If `week` is set to an integer, this function will attempt
 686        to load team game PPA data from games in that season, and in that week.
 687
 688    `team` (str, optional):
 689        Optional argument.
 690        If you only want team game PPA data for a team,
 691        regardless if they are the home/away team,
 692        set `team` to the name of the team you want team game PPA data from.
 693
 694    `conference` (str, optional):
 695        Optional argument.
 696        If you only want team game PPA data from games
 697        involving teams a specific conference,
 698        set `conference` to the abbreviation
 699        of the conference you want team game PPA data from.
 700
 701    `exclude_garbage_time` (bool, optional):
 702        Optional argument.
 703        If you want to filter out plays where
 704        the result of the game is largely decided,
 705        set `exclude_garbage_time = True`.
 706        Default behavior is that this variable is set to
 707        `False` when this function is called.
 708
 709    `season_type` (str, semi-optional):
 710        Semi-optional argument.
 711        By default, this will be set to "regular", for the CFB regular season.
 712        If you want team game PPA data for non-regular season games,
 713        set `season_type` to "postseason".
 714        If `season_type` is set to anything but "regular" or "postseason",
 715        a `ValueError()` will be raised.
 716
 717    `return_as_dict` (bool, semi-optional):
 718        Semi-optional argument.
 719        If you want this function to return
 720        the data as a dictionary (read: JSON object),
 721        instead of a pandas `DataFrame` object,
 722        set `return_as_dict` to `True`.
 723
 724    Usage
 725    ----------
 726    ```
 727    import time
 728
 729    from cfbd_json_py.metrics import get_cfbd_team_game_ppa_data
 730
 731
 732    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
 733
 734    if cfbd_key != "tigersAreAwesome":
 735        print(
 736            "Using the user's API key declared in this script " +
 737            "for this example."
 738        )
 739
 740        # Get team PPA data for individual games within the 2020 CFB season.
 741        print(
 742            "Get team PPA data for individual games " +
 743            "within the 2020 CFB season."
 744        )
 745        json_data = get_cfbd_team_game_ppa_data(
 746            api_key=cfbd_key,
 747            season=2020
 748        )
 749        print(json_data)
 750        time.sleep(5)
 751
 752        # Get team PPA data for week 10 games within the 2020 CFB season.
 753        print(
 754            "Get team PPA data for week 10 games within the 2020 CFB season."
 755        )
 756        json_data = get_cfbd_team_game_ppa_data(
 757            api_key=cfbd_key,
 758            season=2020,
 759            week=10
 760        )
 761        print(json_data)
 762        time.sleep(5)
 763
 764        # Get team PPA data for
 765        # University of Cincinnati football games within the 2020 CFB season.
 766        print(
 767            "Get team PPA data for University of Cincinnati " +
 768            "football games within the 2020 CFB season."
 769        )
 770        json_data = get_cfbd_team_game_ppa_data(
 771            api_key=cfbd_key,
 772            season=2020,
 773            team="Cincinnati"
 774        )
 775        print(json_data)
 776        time.sleep(5)
 777
 778        # Get team PPA data for Southeastern Conference (SEC)
 779        # games within the 2020 CFB season.
 780        print(
 781            "Get team PPA data for Southeastern Conference (SEC) " +
 782            "games within the 2020 CFB season."
 783        )
 784        json_data = get_cfbd_team_game_ppa_data(
 785            api_key=cfbd_key,
 786            season=2020,
 787            conference="SEC"
 788        )
 789        print(json_data)
 790        time.sleep(5)
 791
 792        # Get team PPA data for Southeastern Conference (SEC)
 793        # games within the 2020 CFB season,
 794        # but exclude plays that occur in garbage time.
 795        print(
 796            "Get team PPA data for Southeastern Conference (SEC) games " +
 797            "within the 2020 CFB season, " +
 798            "but exclude plays that occur in garbage time."
 799        )
 800        json_data = get_cfbd_team_game_ppa_data(
 801            api_key=cfbd_key,
 802            season=2020,
 803            conference="SEC",
 804            exclude_garbage_time=True
 805        )
 806        print(json_data)
 807        time.sleep(5)
 808
 809        # Get team PPA data for postseason games in the 2020 CFB season.
 810        print("Get team PPA data for postseason games in the 2020 CFB season.")
 811        json_data = get_cfbd_team_game_ppa_data(
 812            api_key=cfbd_key,
 813            season=2020,
 814            season_type="postseason"
 815        )
 816        print(json_data)
 817        time.sleep(5)
 818
 819        # You can also tell this function to just return the API call as
 820        # a Dictionary (read: JSON) object.
 821        print(
 822            "You can also tell this function to just return the API call " +
 823            "as a Dictionary (read: JSON) object."
 824        )
 825        json_data = get_cfbd_team_game_ppa_data(
 826            api_key=cfbd_key,
 827            season=2020,
 828            team="Cincinnati",
 829            return_as_dict=True
 830        )
 831        print(json_data)
 832
 833    else:
 834        # Alternatively, if the CFBD API key exists in this python environment,
 835        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
 836        # you could just call these functions directly,
 837        # without setting the API key in the script.
 838        print(
 839            "Using the user's API key supposedly loaded into this " +
 840            "python environment for this example."
 841        )
 842
 843        # Get team PPA data for individual games within the 2020 CFB season.
 844        print(
 845            "Get team PPA data for individual games " +
 846            "within the 2020 CFB season."
 847        )
 848        json_data = get_cfbd_team_game_ppa_data(
 849            season=2020
 850        )
 851        print(json_data)
 852        time.sleep(5)
 853
 854        # Get team PPA data for week 10 games within the 2020 CFB season.
 855        print(
 856            "Get team PPA data for week 10 games within the 2020 CFB season."
 857        )
 858        json_data = get_cfbd_team_game_ppa_data(
 859            season=2020,
 860            week=10
 861        )
 862        print(json_data)
 863        time.sleep(5)
 864
 865        # Get team PPA data for
 866        # University of Cincinnati football games within the 2020 CFB season.
 867        print(
 868            "Get team PPA data for University of Cincinnati football " +
 869            "games within the 2020 CFB season."
 870        )
 871        json_data = get_cfbd_team_game_ppa_data(
 872            season=2020,
 873            team="Cincinnati"
 874        )
 875        print(json_data)
 876        time.sleep(5)
 877
 878        # Get team PPA data for Southeastern Conference (SEC)
 879        # games within the 2020 CFB season.
 880        print(
 881            "Get team PPA data for Southeastern Conference (SEC) games " +
 882            "within the 2020 CFB season."
 883        )
 884        json_data = get_cfbd_team_game_ppa_data(
 885            season=2020,
 886            conference="SEC"
 887        )
 888        print(json_data)
 889        time.sleep(5)
 890
 891        # Get team PPA data for Southeastern Conference (SEC)
 892        # games within the 2020 CFB season,
 893        # but exclude plays that occur in garbage time.
 894        print(
 895            "Get team PPA data for Southeastern Conference (SEC) games " +
 896            "within the 2020 CFB season, " +
 897            "but exclude plays that occur in garbage time."
 898        )
 899        json_data = get_cfbd_team_game_ppa_data(
 900            season=2020,
 901            conference="SEC",
 902            exclude_garbage_time=True
 903        )
 904        print(json_data)
 905        time.sleep(5)
 906
 907        # Get team PPA data for postseason games in the 2020 CFB season.
 908        print("Get team PPA data for postseason games in the 2020 CFB season.")
 909        json_data = get_cfbd_team_game_ppa_data(
 910            season=2020,
 911            season_type="postseason"
 912        )
 913        print(json_data)
 914        time.sleep(5)
 915
 916        # You can also tell this function to just return the API call as
 917        # a Dictionary (read: JSON) object.
 918        print(
 919            "You can also tell this function to just return the API call " +
 920            "as a Dictionary (read: JSON) object."
 921        )
 922        json_data = get_cfbd_team_game_ppa_data(
 923            season=2020,
 924            team="Cincinnati",
 925            return_as_dict=True
 926        )
 927        print(json_data)
 928
 929    ```
 930    Returns
 931    ----------
 932    A pandas `DataFrame` object with team PPA data,
 933    or (if `return_as_dict` is set to `True`)
 934    a dictionary object with team PPA data.
 935
 936    """
 937
 938    now = datetime.now()
 939    cfb_games_df = pd.DataFrame()
 940    # row_df = pd.DataFrame()
 941    url = "https://api.collegefootballdata.com/ppa/games"
 942
 943    ##########################################################################
 944
 945    if api_key is not None:
 946        real_api_key = api_key
 947        del api_key
 948    else:
 949        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
 950
 951    if real_api_key == "tigersAreAwesome":
 952        raise ValueError(
 953            "You actually need to change `cfbd_key` to your CFBD API key."
 954        )
 955    elif "Bearer " in real_api_key:
 956        pass
 957    elif "Bearer" in real_api_key:
 958        real_api_key = real_api_key.replace("Bearer", "Bearer ")
 959    else:
 960        real_api_key = "Bearer " + real_api_key
 961
 962    if season is None:
 963        # This should never happen without user tampering, but if it does,
 964        # we need to raise an error,
 965        # because the CFBD API will refuse this call without a valid season.
 966        raise SystemError(
 967            "I don't know how, I don't know why, "
 968            + "but you managed to call this function "
 969            + "while `season` was `None` (NULL),"
 970            + " and the function got to this point in the code."
 971            + "\nIf you have a GitHub account, "
 972            + "please raise an issue on this python package's GitHub page:\n"
 973            + "https://github.com/armstjc/cfbd-json-py/issues"
 974        )
 975    elif season > (now.year + 1):
 976        raise ValueError(f"`season` cannot be greater than {season}.")
 977    elif season < 1869:
 978        raise ValueError("`season` cannot be less than 1869.")
 979
 980    if season_type != "regular" and season_type != "postseason":
 981        raise ValueError(
 982            "`season_type` must be set to either "
 983            + '"regular" or "postseason" for this function to work.'
 984        )
 985
 986    if week is not None and week < 0:
 987        raise ValueError("`week` must be a positive number.")
 988
 989    if season_type != "regular" and season_type != "postseason":
 990        raise ValueError(
 991            "`season_type` must be set to either "
 992            + '"regular" or "postseason" for this function to work.'
 993        )
 994
 995    gt_str = ""
 996    if exclude_garbage_time is True:
 997        gt_str = "true"
 998    elif exclude_garbage_time is False:
 999        gt_str = "false"
1000
1001    # URL builder
1002    ##########################################################################
1003
1004    # Required by API
1005    url += f"?seasonType={season_type}"
1006    url += f"&year={season}"
1007
1008    if week is not None:
1009        url += f"&week={week}"
1010
1011    if team is not None:
1012        url += f"&team={team}"
1013
1014    if conference is not None:
1015        url += f"&conference={conference}"
1016
1017    if exclude_garbage_time is not None:
1018        url += f"&excludeGarbageTime={gt_str}"
1019
1020    headers = {
1021        "Authorization": f"{real_api_key}", "accept": "application/json"
1022    }
1023    response = requests.get(url, headers=headers)
1024
1025    if response.status_code == 200:
1026        pass
1027    elif response.status_code == 401:
1028        raise ConnectionRefusedError(
1029            "Could not connect. The connection was refused.\n" +
1030            "HTTP Status Code 401."
1031        )
1032    else:
1033        raise ConnectionError(
1034            f"Could not connect.\nHTTP Status code {response.status_code}"
1035        )
1036
1037    json_data = response.json()
1038
1039    if return_as_dict is True:
1040        return json_data
1041
1042    cfb_games_df = pd.json_normalize(json_data)
1043    cfb_games_df.rename(
1044        columns={
1045            "gameId": "game_id",
1046            "conference": "conference_name",
1047            "team": "team_name",
1048            "opponent": "opponent_name",
1049            "offense.overall": "ppa_offense_overall",
1050            "offense.passing": "ppa_offense_passing",
1051            "offense.rushing": "ppa_offense_rushing",
1052            "offense.firstDown": "ppa_offense_first_down",
1053            "offense.secondDown": "ppa_offense_second_down",
1054            "offense.thirdDown": "ppa_offense_third_down",
1055            "offense.cumulative.total": "ppa_offense_cumulative_total",
1056            "offense.cumulative.passing": "ppa_offense_cumulative_passing",
1057            "offense.cumulative.rushing": "ppa_offense_cumulative_rushing",
1058            "defense.overall": "ppa_defense_overall",
1059            "defense.passing": "ppa_defense_passing",
1060            "defense.rushing": "ppa_defense_rushing",
1061            "defense.firstDown": "ppa_defense_first_down",
1062            "defense.secondDown": "ppa_defense_second_down",
1063            "defense.thirdDown": "ppa_defense_third_down",
1064            "defense.cumulative.total": "ppa_defense_cumulative_total",
1065            "defense.cumulative.passing": "ppa_defense_cumulative_passing",
1066            "defense.cumulative.rushing": "ppa_defense_cumulative_rushing",
1067        },
1068        inplace=True,
1069    )
1070    return cfb_games_df
1071
1072
1073def get_cfbd_player_game_ppa_data(
1074    api_key: str = None,
1075    api_key_dir: str = None,
1076    season: int = None,
1077    week: int = None,
1078    team: str = None,
1079    # A week or team must be specified
1080    position: str = None,
1081    player_id: int = None,
1082    play_threshold: int = None,
1083    exclude_garbage_time: bool = False,
1084    season_type: str = "regular",  # "regular" or "postseason"
1085    return_as_dict: bool = False,
1086):
1087    """
1088    Allows you to get player PPA data,
1089    at a game level,
1090    with or without garbage time plays,
1091    for a specified time period and/or team.
1092
1093    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
1094
1095    Parameters
1096    ----------
1097
1098    `api_key` (str, optional):
1099        Semi-optional argument.
1100        If `api_key` is null, this function will attempt to load a CFBD API key
1101        from the python environment, or from a file on this computer.
1102        If `api_key` is not null,
1103        this function will automatically assume that the
1104        inputted `api_key` is a valid CFBD API key.
1105
1106    `api_key_dir` (str, optional):
1107        Optional argument.
1108        If `api_key` is set to am empty string, this variable is ignored.
1109        If `api_key_dir` is null, and `api_key` is null,
1110        this function will try to find
1111        a CFBD API key file in this user's home directory.
1112        If `api_key_dir` is set to a string, and `api_key` is null,
1113        this function will assume that `api_key_dir` is a directory,
1114        and will try to find a CFBD API key file in that directory.
1115
1116    `season` (int, semi-optional):
1117        Semi-Optional argument.
1118        Specifies the season you want player game PPA data information from.
1119        This must be specified, otherwise this package, and by extension
1120        the CFBD API, will not accept the request
1121        to get player game PPA data information.
1122
1123    `week` (int, semi-optional):
1124        Semi-Optional argument.
1125        If `week` is set to an integer, this function will attempt
1126        to load player game PPA data from
1127        games in that season, and in that week.
1128        `week` and/or `team` must be set to a non-null value for this function
1129        to work.
1130
1131    `team` (str, semi-optional):
1132        Semi-Optional argument.
1133        If you only want player game PPA data for players of a specific team,
1134        regardless if they are the home/away team,
1135        set `team` to the name of the team you want player game PPA data from.
1136        `week` and/or `team` must be set to a non-null value for this function
1137        to work.
1138
1139    `position` (str, optional):
1140        Optional argument.
1141        If you only want player game PPA data
1142        for players of a specific position,
1143        set `position` to the position you want player game PPA data from.
1144
1145    `player_id` (int, optional):
1146        Optional argument.
1147        If you only want PPA data for a specific player ID,
1148        set this variable to the player ID
1149        of the player you want PPA data from.
1150
1151    `play_threshold`
1152        Optional argument.
1153        If you only want PPA data for players
1154        who touched the ball for *X* number of plays in a game,
1155        set `play_threshold = x`, where `x` is
1156        your specified minimum number of plays.
1157
1158    `exclude_garbage_time` (bool, optional):
1159        Optional argument.
1160        If you want to filter out plays where
1161        the result of the game is largely decided,
1162        set `exclude_garbage_time = True`.
1163        Default behavior is that this variable is set to
1164        `False` when this function is called.
1165
1166    `season_type` (str, semi-optional):
1167        Semi-optional argument.
1168        By default, this will be set to "regular", for the CFB regular season.
1169        If you want player game PPA data for non-regular season games,
1170        set `season_type` to "postseason".
1171        If `season_type` is set to anything but "regular" or "postseason",
1172        a `ValueError()` will be raised.
1173
1174    `return_as_dict` (bool, semi-optional):
1175        Semi-optional argument.
1176        If you want this function to return
1177        the data as a dictionary (read: JSON object),
1178        instead of a pandas `DataFrame` object,
1179        set `return_as_dict` to `True`.
1180
1181    Usage
1182    ----------
1183    ```
1184    import time
1185
1186    from cfbd_json_py.metrics import get_cfbd_player_game_ppa_data
1187
1188
1189    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
1190
1191    if cfbd_key != "tigersAreAwesome":
1192        print(
1193            "Using the user's API key declared in this script " +
1194            "for this example."
1195        )
1196
1197        # Get player game PPA data for week 10 of the 2020 CFB season.
1198        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1199        json_data = get_cfbd_player_game_ppa_data(
1200            api_key=cfbd_key,
1201            season=2020,
1202            week=10
1203        )
1204        print(json_data)
1205        time.sleep(5)
1206
1207        # Get player game PPA data for players of the
1208        # 2020 University of Cincinnati Football team.
1209        print(
1210            "Get player game PPA data for players of " +
1211            "the 2020 University of Cincinnati Football team."
1212        )
1213        json_data = get_cfbd_player_game_ppa_data(
1214            api_key=cfbd_key,
1215            season=2020,
1216            team="Cincinnati"
1217        )
1218        print(json_data)
1219        time.sleep(5)
1220
1221        # Get player game PPA data for QBs who played
1222        # in week 10 of the 2020 CFB season.
1223        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1224        json_data = get_cfbd_player_game_ppa_data(
1225            api_key=cfbd_key,
1226            season=2020,
1227            week=10,
1228            position="QB"
1229        )
1230        print(json_data)
1231        time.sleep(5)
1232
1233        # Get player game PPA data for QBs who
1234        # played in week 10 of the 2020 CFB season,
1235        # but exclude plays in garbage time.
1236        print(
1237            "Get player game PPA data for week 10 of the 2020 CFB season, " +
1238            "but exclude plays in garbage time."
1239        )
1240        json_data = get_cfbd_player_game_ppa_data(
1241            api_key=cfbd_key,
1242            season=2020,
1243            week=10,
1244            position="QB",
1245            exclude_garbage_time=True
1246        )
1247        print(json_data)
1248        time.sleep(5)
1249
1250        # Get player game PPA data for week 10 of the 2020 CFB season,
1251        # where a player touched the ball for at least 25 plays.
1252        print(
1253            "Get player game PPA data for week 10 of the 2020 " +
1254            "CFB season, where a player touched the ball " +
1255            "for at least 25 plays."
1256        )
1257        json_data = get_cfbd_player_game_ppa_data(
1258            api_key=cfbd_key,
1259            season=2020,
1260            week=10,
1261            play_threshold=25
1262        )
1263        print(json_data)
1264        time.sleep(5)
1265
1266        # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
1267        # during their postseason.
1268        print(
1269            "Get player game PPA data the 2020 Alabama Crimson Tide " +
1270            "Football team, during their postseason."
1271        )
1272        json_data = get_cfbd_player_game_ppa_data(
1273            api_key=cfbd_key,
1274            season=2020,
1275            team="Alabama",
1276            season_type="postseason"
1277        )
1278        print(json_data)
1279        time.sleep(5)
1280
1281        # You can also tell this function to just return the API call as
1282        # a Dictionary (read: JSON) object.
1283        print(
1284            "You can also tell this function to just return the API call " +
1285            "as a Dictionary (read: JSON) object."
1286        )
1287        json_data = get_cfbd_player_game_ppa_data(
1288            api_key=cfbd_key,
1289            season=2020,
1290            week=10,
1291            return_as_dict=True
1292        )
1293        print(json_data)
1294
1295    else:
1296        # Alternatively, if the CFBD API key exists in this python environment,
1297        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
1298        # you could just call these functions directly,
1299        # without setting the API key in the script.
1300        print(
1301            "Using the user's API key supposedly loaded into " +
1302            "this python environment for this example."
1303        )
1304
1305        # Get player game PPA data for week 10 of the 2020 CFB season.
1306        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1307        json_data = get_cfbd_player_game_ppa_data(
1308            season=2020,
1309            week=10
1310        )
1311        print(json_data)
1312        time.sleep(5)
1313
1314        # Get player game PPA data for players of the
1315        # 2020 University of Cincinnati Football team.
1316        print(
1317            "Get player game PPA data for players of " +
1318            "the 2020 University of Cincinnati Football team."
1319        )
1320        json_data = get_cfbd_player_game_ppa_data(
1321            season=2020,
1322            team="Cincinnati"
1323        )
1324        print(json_data)
1325        time.sleep(5)
1326
1327        # Get player game PPA data for QBs who played
1328        # in week 10 of the 2020 CFB season.
1329        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1330        json_data = get_cfbd_player_game_ppa_data(
1331            season=2020,
1332            week=10,
1333            position="QB"
1334        )
1335        print(json_data)
1336        time.sleep(5)
1337
1338        # Get player game PPA data for QBs who played
1339        # in week 10 of the 2020 CFB season,
1340        # but exclude plays in garbage time.
1341        print(
1342            "Get player game PPA data for week 10 of the 2020 CFB season, " +
1343            "but exclude plays in garbage time."
1344        )
1345        json_data = get_cfbd_player_game_ppa_data(
1346            season=2020,
1347            week=10,
1348            position="QB",
1349            exclude_garbage_time=True
1350        )
1351        print(json_data)
1352        time.sleep(5)
1353
1354        # Get player game PPA data for week 10 of the 2020 CFB season,
1355        # where a player touched the ball for at least 25 plays.
1356        print(
1357            "Get player game PPA data for week 10 of the 2020 CFB season," +
1358            " where a player touched the ball for at least 25 plays."
1359        )
1360        json_data = get_cfbd_player_game_ppa_data(
1361            season=2020,
1362            week=10,
1363            play_threshold=25
1364        )
1365        print(json_data)
1366        time.sleep(5)
1367
1368        # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
1369        # during their postseason.
1370        print(
1371            "Get player game PPA data the 2020 Alabama Crimson Tide " +
1372            "Football team, during their postseason."
1373        )
1374        json_data = get_cfbd_player_game_ppa_data(
1375            season=2020,
1376            team="Alabama",
1377            season_type="postseason"
1378        )
1379        print(json_data)
1380        time.sleep(5)
1381
1382        # You can also tell this function to just return the API call as
1383        # a Dictionary (read: JSON) object.
1384        print(
1385            "You can also tell this function to just return the API call " +
1386            "as a Dictionary (read: JSON) object."
1387        )
1388        json_data = get_cfbd_player_game_ppa_data(
1389            season=2020,
1390            week=10,
1391            return_as_dict=True
1392        )
1393        print(json_data)
1394
1395    ```
1396    Returns
1397    ----------
1398    A pandas `DataFrame` object with player PPA data,
1399    or (if `return_as_dict` is set to `True`)
1400    a dictionary object with player PPA data.
1401
1402    """
1403
1404    now = datetime.now()
1405    cfb_games_df = pd.DataFrame()
1406    # row_df = pd.DataFrame()
1407    url = "https://api.collegefootballdata.com/ppa/players/games"
1408
1409    ##########################################################################
1410
1411    if api_key is not None:
1412        real_api_key = api_key
1413        del api_key
1414    else:
1415        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
1416
1417    if real_api_key == "tigersAreAwesome":
1418        raise ValueError(
1419            "You actually need to change `cfbd_key` to your CFBD API key."
1420        )
1421    elif "Bearer " in real_api_key:
1422        pass
1423    elif "Bearer" in real_api_key:
1424        real_api_key = real_api_key.replace("Bearer", "Bearer ")
1425    else:
1426        real_api_key = "Bearer " + real_api_key
1427
1428    if season is None:
1429        # This should never happen without user tampering, but if it does,
1430        # we need to raise an error,
1431        # because the CFBD API will refuse this call without a valid season.
1432        raise SystemError(
1433            "I don't know how, I don't know why, but you managed "
1434            + "to call this function while `season` was `None` (NULL),"
1435            + " and the function got to this point in the code."
1436            + "\nIf you have a GitHub account, "
1437            + "please raise an issue on this python package's GitHub page:\n"
1438            + "https://github.com/armstjc/cfbd-json-py/issues"
1439        )
1440    elif season > (now.year + 1):
1441        raise ValueError(f"`season` cannot be greater than {season}.")
1442    elif season < 1869:
1443        raise ValueError("`season` cannot be less than 1869.")
1444
1445    if week is None and team is None:
1446        raise ValueError(
1447            "To call this function, you must set `week` and/or `team` "
1448            + "to a non-null value."
1449        )
1450
1451    if season_type != "regular" and season_type != "postseason":
1452        raise ValueError(
1453            '`season_type` must be set to either ' +
1454            '"regular" or "postseason" for this function to work.'
1455        )
1456
1457    if week is not None and week < 0:
1458        raise ValueError("`week` must be a positive number.")
1459
1460    if season_type != "regular" and season_type != "postseason":
1461        raise ValueError(
1462            '`season_type` must be set to either ' +
1463            '"regular" or "postseason" for this function to work.'
1464        )
1465
1466    if play_threshold is not None and play_threshold < 0:
1467        raise ValueError(
1468            "`play_threshold` must be an integer at or greater than 0."
1469        )
1470
1471    gt_str = ""
1472    if exclude_garbage_time is True:
1473        gt_str = "true"
1474    elif exclude_garbage_time is False:
1475        gt_str = "false"
1476
1477    # URL builder
1478    ##########################################################################
1479
1480    url_elements = 0
1481
1482    if season is not None and url_elements == 0:
1483        url += f"?year={season}"
1484        url_elements += 1
1485    elif season is not None:
1486        url += f"&year={season}"
1487        url_elements += 1
1488
1489    if week is not None and url_elements == 0:
1490        url += f"?week={week}"
1491        url_elements += 1
1492    elif week is not None:
1493        url += f"&week={week}"
1494        url_elements += 1
1495
1496    if team is not None and url_elements == 0:
1497        url += f"?team={team}"
1498        url_elements += 1
1499    elif team is not None:
1500        url += f"&team={team}"
1501        url_elements += 1
1502
1503    if position is not None and url_elements == 0:
1504        url += f"?position={position}"
1505        url_elements += 1
1506    elif position is not None:
1507        url += f"&position={position}"
1508        url_elements += 1
1509
1510    if player_id is not None and url_elements == 0:
1511        url += f"?playerId={player_id}"
1512        url_elements += 1
1513    elif player_id is not None:
1514        url += f"&playerId={player_id}"
1515        url_elements += 1
1516
1517    if play_threshold is not None and url_elements == 0:
1518        url += f"?threshold={play_threshold}"
1519        url_elements += 1
1520    elif play_threshold is not None:
1521        url += f"&threshold={play_threshold}"
1522        url_elements += 1
1523
1524    if exclude_garbage_time is not None and url_elements == 0:
1525        url += f"?excludeGarbageTime={gt_str}"
1526        url_elements += 1
1527    elif exclude_garbage_time is not None:
1528        url += f"&excludeGarbageTime={gt_str}"
1529        url_elements += 1
1530
1531    if season_type is not None and url_elements == 0:
1532        url += f"?seasonType={season_type}"
1533        url_elements += 1
1534    elif season_type is not None:
1535        url += f"&seasonType={season_type}"
1536        url_elements += 1
1537
1538    headers = {
1539        "Authorization": f"{real_api_key}", "accept": "application/json"
1540    }
1541    response = requests.get(url, headers=headers)
1542
1543    if response.status_code == 200:
1544        pass
1545    elif response.status_code == 401:
1546        raise ConnectionRefusedError(
1547            "Could not connect. The connection was refused.\n" +
1548            "HTTP Status Code 401."
1549        )
1550    else:
1551        raise ConnectionError(
1552            f"Could not connect.\nHTTP Status code {response.status_code}"
1553        )
1554
1555    json_data = response.json()
1556
1557    if return_as_dict is True:
1558        return json_data
1559
1560    cfb_games_df = pd.json_normalize(json_data)
1561    cfb_games_df.rename(
1562        columns={
1563            "name": "player_name",
1564            "position": "position_abv",
1565            "team": "team_name",
1566            "opponent": "opponent_name",
1567            "averagePPA.all": "avg_ppa_cumulative",
1568            "averagePPA.pass": "avg_ppa_pass",
1569            "averagePPA.rush": "avg_ppa_rush",
1570        },
1571        inplace=True,
1572    )
1573
1574    return cfb_games_df
1575
1576
1577def get_cfbd_player_season_ppa_data(
1578    api_key: str = None,
1579    api_key_dir: str = None,
1580    season: int = None,
1581    team: str = None,
1582    conference: str = None,
1583    position: str = None,
1584    player_id: int = None,
1585    play_threshold: int = None,
1586    exclude_garbage_time: bool = False,
1587    return_as_dict: bool = False,
1588):
1589    """
1590    Allows you to get player PPA data,
1591    at a season level,
1592    with or without garbage time plays,
1593    for a specified time period and/or team.
1594
1595    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
1596
1597    Parameters
1598    ----------
1599
1600    `api_key` (str, optional):
1601        Semi-optional argument.
1602        If `api_key` is null, this function will attempt to load a CFBD API key
1603        from the python environment, or from a file on this computer.
1604        If `api_key` is not null,
1605        this function will automatically assume that the
1606        inputted `api_key` is a valid CFBD API key.
1607
1608    `api_key_dir` (str, optional):
1609        Optional argument.
1610        If `api_key` is set to am empty string, this variable is ignored.
1611        If `api_key_dir` is null, and `api_key` is null,
1612        this function will try to find
1613        a CFBD API key file in this user's home directory.
1614        If `api_key_dir` is set to a string, and `api_key` is null,
1615        this function will assume that `api_key_dir` is a directory,
1616        and will try to find a CFBD API key file in that directory.
1617
1618    `season` (int, semi-optional):
1619        Semi-Optional argument.
1620        Specifies the season you want player season PPA data information from.
1621        This must be specified, otherwise this package, and by extension
1622        the CFBD API, will not accept the request
1623        to get player season PPA data information.
1624
1625
1626    `team` (str, semi-optional):
1627        Semi-Optional argument.
1628        If you only want player season PPA data for players of a specific team,
1629        regardless if they are the home/away team,
1630        set `team` to the name of the team
1631        you want player season PPA data from.
1632        `week` and/or `team` must be set to a non-null value for this function
1633        to work.
1634
1635    `conference` (str, optional):
1636        Optional argument.
1637        If you only want player season PPA data from games
1638        involving teams from a specific conference,
1639        set `conference` to the abbreviation
1640        of the conference you want player season PPA data from.
1641        For a list of conferences,
1642        use the `cfbd_json_py.conferences.get_cfbd_conference_info()`
1643        function.
1644
1645    `position` (str, optional):
1646        Optional argument.
1647        If you only want player season PPA data
1648        for players of a specific position,
1649        set `position` to the position you want player season PPA data from.
1650
1651    `player_id` (int, optional):
1652        Optional argument.
1653        If you only want PPA data for a specific player ID,
1654        set this variable to the player ID
1655        of the player you want PPA data from.
1656
1657    `play_threshold`
1658        Optional argument.
1659        If you only want PPA data for players
1660        who touched the ball for *X* number of plays in a game,
1661        set `play_threshold = x`, where `x` is
1662        your specified minimum number of plays.
1663
1664    `exclude_garbage_time` (bool, optional):
1665        Optional argument.
1666        If you want to filter out plays where
1667        the result of the game is largely decided,
1668        set `exclude_garbage_time = True`.
1669        Default behavior is that this variable is set to
1670        `False` when this function is called.
1671
1672
1673    `return_as_dict` (bool, semi-optional):
1674        Semi-optional argument.
1675        If you want this function to return the data
1676        as a dictionary (read: JSON object),
1677        instead of a pandas `DataFrame` object,
1678        set `return_as_dict` to `True`.
1679
1680    Usage
1681    ----------
1682    ```
1683    import time
1684
1685    from cfbd_json_py.metrics import get_cfbd_player_season_ppa_data
1686
1687
1688    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
1689
1690    if cfbd_key != "tigersAreAwesome":
1691        print(
1692            "Using the user's API key declared in this script " +
1693            "for this example."
1694        )
1695
1696        # Get player season PPA data for the 2020 CFB season.
1697        print("Get player season PPA data for the 2020 CFB season.")
1698        json_data = get_cfbd_player_season_ppa_data(
1699            api_key=cfbd_key,
1700            season=2020
1701        )
1702        print(json_data)
1703        time.sleep(5)
1704
1705        # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
1706        print(
1707            "Get player season PPA data for " +
1708            "the 2020 Ohio Bobcats Football Team."
1709        )
1710        json_data = get_cfbd_player_season_ppa_data(
1711            api_key=cfbd_key,
1712            season=2020,
1713            team="Ohio"
1714        )
1715        print(json_data)
1716        time.sleep(5)
1717
1718        # Get player season PPA data for players who played on
1719        # teams within the Southeastern Conference (SEC) for the
1720        # 2020 CFB Season.
1721        print(
1722            "Get player season PPA data for players who played on teams " +
1723            "within the Southeastern Conference (SEC) for the 2020 CFB Season."
1724        )
1725        json_data = get_cfbd_player_season_ppa_data(
1726            api_key=cfbd_key,
1727            season=2020,
1728            conference="SEC"
1729        )
1730        print(json_data)
1731        time.sleep(5)
1732
1733        # Get player season PPA data from QBs in the 2020 CFB Season.
1734        print("Get player season PPA data from QBs in the 2020 CFB Season.")
1735        json_data = get_cfbd_player_season_ppa_data(
1736            api_key=cfbd_key,
1737            season=2020,
1738            position="QB"
1739        )
1740        print(json_data)
1741        time.sleep(5)
1742
1743        # Get player season PPA data from
1744        # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
1745        print(
1746            "Get player season PPA data from former " +
1747            "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
1748        )
1749        json_data = get_cfbd_player_season_ppa_data(
1750            api_key=cfbd_key,
1751            player_id=3915511
1752        )
1753        print(json_data)
1754        time.sleep(5)
1755
1756        # Get player season PPA data from
1757        # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
1758        # but exclude plays that occurred in garbage time.
1759        print(
1760            "Get player season PPA data from former " +
1761            "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
1762            "but exclude plays that occurred in garbage time."
1763        )
1764        json_data = get_cfbd_player_season_ppa_data(
1765            api_key=cfbd_key,
1766            player_id=3915511,
1767            exclude_garbage_time=True
1768        )
1769        print(json_data)
1770        time.sleep(5)
1771
1772        # Get player season PPA data from the 2020 CFB Season,
1773        # for players with at least 100 plays/touches.
1774        print(
1775            "Get player season PPA data from the 2020 CFB Season, " +
1776            "for players with at least 100 plays/touches."
1777        )
1778        json_data = get_cfbd_player_season_ppa_data(
1779            api_key=cfbd_key,
1780            season=2020,
1781            play_threshold=100
1782        )
1783        print(json_data)
1784        time.sleep(5)
1785
1786        # You can also tell this function to just return the API call as
1787        # a Dictionary (read: JSON) object.
1788        print(
1789            "You can also tell this function to just return the API call " +
1790            "as a Dictionary (read: JSON) object."
1791        )
1792        json_data = get_cfbd_player_season_ppa_data(
1793            api_key=cfbd_key,
1794            season=2020,
1795            return_as_dict=True
1796        )
1797        print(json_data)
1798
1799    else:
1800        # Alternatively, if the CFBD API key exists in this python environment,
1801        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
1802        # you could just call these functions directly,
1803        # without setting the API key in the script.
1804        print(
1805            "Using the user's API key supposedly loaded into " +
1806            "this python environment for this example."
1807        )
1808
1809        # Get player season PPA data for the 2020 CFB season.
1810        print("Get player season PPA data for the 2020 CFB season.")
1811        json_data = get_cfbd_player_season_ppa_data(
1812            season=2020
1813        )
1814        print(json_data)
1815        time.sleep(5)
1816
1817        # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
1818        print(
1819            "Get player season PPA data for " +
1820            "the 2020 Ohio Bobcats Football Team."
1821        )
1822        json_data = get_cfbd_player_season_ppa_data(
1823            season=2020,
1824            team="Ohio"
1825        )
1826        print(json_data)
1827        time.sleep(5)
1828
1829        # Get player season PPA data for players who played on
1830        # teams within the Southeastern Conference (SEC) for the
1831        # 2020 CFB Season.
1832        print(
1833            "Get player season PPA data for players who played on teams " +
1834            "within the Southeastern Conference (SEC) for the 2020 CFB Season."
1835        )
1836        json_data = get_cfbd_player_season_ppa_data(
1837            season=2020,
1838            conference="SEC"
1839        )
1840        print(json_data)
1841        time.sleep(5)
1842
1843        # Get player season PPA data from QBs in the 2020 CFB Season.
1844        print("Get player season PPA data from QBs in the 2020 CFB Season.")
1845        json_data = get_cfbd_player_season_ppa_data(
1846            season=2020,
1847            position="QB"
1848        )
1849        print(json_data)
1850        time.sleep(5)
1851
1852        # Get player season PPA data from
1853        # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
1854        print(
1855            "Get player season PPA data from former " +
1856            "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
1857        )
1858        json_data = get_cfbd_player_season_ppa_data(
1859            player_id=3915511
1860        )
1861        print(json_data)
1862        time.sleep(5)
1863
1864        # Get player season PPA data from
1865        # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
1866        # but exclude plays that occurred in garbage time.
1867        print(
1868            "Get player season PPA data from former " +
1869            "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
1870            "but exclude plays that occurred in garbage time."
1871        )
1872        json_data = get_cfbd_player_season_ppa_data(
1873            player_id=3915511,
1874            exclude_garbage_time=True
1875        )
1876        print(json_data)
1877        time.sleep(5)
1878
1879        # Get player season PPA data from the 2020 CFB Season,
1880        # for players with at least 100 plays/touches.
1881        print(
1882            "Get player season PPA data from the 2020 CFB Season, " +
1883            "for players with at least 100 plays/touches."
1884        )
1885        json_data = get_cfbd_player_season_ppa_data(
1886            season=2020,
1887            play_threshold=100
1888        )
1889        print(json_data)
1890        time.sleep(5)
1891
1892        # You can also tell this function to just return the API call as
1893        # a Dictionary (read: JSON) object.
1894        print(
1895            "You can also tell this function to just return the API call " +
1896            "as a Dictionary (read: JSON) object."
1897        )
1898        json_data = get_cfbd_player_season_ppa_data(
1899            season=2020,
1900            return_as_dict=True
1901        )
1902        print(json_data)
1903
1904    ```
1905    Returns
1906    ----------
1907    A pandas `DataFrame` object with player PPA data,
1908    or (if `return_as_dict` is set to `True`)
1909    a dictionary object with player PPA data.
1910
1911    """
1912    now = datetime.now()
1913    cfb_games_df = pd.DataFrame()
1914    # row_df = pd.DataFrame()
1915    url = "https://api.collegefootballdata.com/ppa/players/season"
1916
1917    ##########################################################################
1918
1919    if api_key is not None:
1920        real_api_key = api_key
1921        del api_key
1922    else:
1923        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
1924
1925    if real_api_key == "tigersAreAwesome":
1926        raise ValueError(
1927            "You actually need to change `cfbd_key` to your CFBD API key."
1928        )
1929    elif "Bearer " in real_api_key:
1930        pass
1931    elif "Bearer" in real_api_key:
1932        real_api_key = real_api_key.replace("Bearer", "Bearer ")
1933    else:
1934        real_api_key = "Bearer " + real_api_key
1935
1936    if season is None:
1937        pass
1938    elif season > (now.year + 1):
1939        raise ValueError(f"`season` cannot be greater than {season}.")
1940    elif season < 1869:
1941        raise ValueError("`season` cannot be less than 1869.")
1942
1943    if play_threshold is not None and play_threshold < 0:
1944        raise ValueError(
1945            "`play_threshold` must be an integer at or greater than 0."
1946        )
1947
1948    gt_str = ""
1949    if exclude_garbage_time is True:
1950        gt_str = "true"
1951    elif exclude_garbage_time is False:
1952        gt_str = "false"
1953
1954    # URL builder
1955    ##########################################################################
1956
1957    url_elements = 0
1958
1959    if season is not None and url_elements == 0:
1960        url += f"?year={season}"
1961        url_elements += 1
1962    elif season is not None:
1963        url += f"&year={season}"
1964        url_elements += 1
1965
1966    if team is not None and url_elements == 0:
1967        url += f"?team={team}"
1968        url_elements += 1
1969    elif team is not None:
1970        url += f"&team={team}"
1971        url_elements += 1
1972
1973    if conference is not None and url_elements == 0:
1974        url += f"?conference={conference}"
1975        url_elements += 1
1976    elif conference is not None:
1977        url += f"&conference={conference}"
1978        url_elements += 1
1979
1980    if position is not None and url_elements == 0:
1981        url += f"?position={position}"
1982        url_elements += 1
1983    elif position is not None:
1984        url += f"&position={position}"
1985        url_elements += 1
1986
1987    if player_id is not None and url_elements == 0:
1988        url += f"?playerId={player_id}"
1989        url_elements += 1
1990    elif player_id is not None:
1991        url += f"&playerId={player_id}"
1992        url_elements += 1
1993
1994    if play_threshold is not None and url_elements == 0:
1995        url += f"?threshold={play_threshold}"
1996        url_elements += 1
1997    elif play_threshold is not None:
1998        url += f"&threshold={play_threshold}"
1999        url_elements += 1
2000
2001    if exclude_garbage_time is not None and url_elements == 0:
2002        url += f"?excludeGarbageTime={gt_str}"
2003        url_elements += 1
2004    elif exclude_garbage_time is not None:
2005        url += f"&excludeGarbageTime={gt_str}"
2006        url_elements += 1
2007
2008    headers = {
2009        "Authorization": f"{real_api_key}", "accept": "application/json"
2010    }
2011    response = requests.get(url, headers=headers)
2012
2013    if response.status_code == 200:
2014        pass
2015    elif response.status_code == 401:
2016        raise ConnectionRefusedError(
2017            "Could not connect. The connection was refused.\n" +
2018            "HTTP Status Code 401."
2019        )
2020    else:
2021        raise ConnectionError(
2022            f"Could not connect.\nHTTP Status code {response.status_code}"
2023        )
2024
2025    json_data = response.json()
2026
2027    if return_as_dict is True:
2028        return json_data
2029
2030    cfb_games_df = pd.json_normalize(json_data)
2031    cfb_games_df.rename(
2032        columns={
2033            "id": "game_id",
2034            "name": "player_name",
2035            "position": "position_abv",
2036            "team": "team_name",
2037            "conference": "conference_name",
2038            "countablePlays": "countable_plays",
2039            "averagePPA.all": "avg_ppa_all",
2040            "averagePPA.pass": "avg_ppa_pass",
2041            "averagePPA.rush": "avg_ppa_rush",
2042            "averagePPA.firstDown": "avg_ppa_first_down",
2043            "averagePPA.secondDown": "avg_ppa_second_down",
2044            "averagePPA.thirdDown": "avg_ppa_third_down",
2045            "averagePPA.standardDowns": "avg_ppa_standard_downs",
2046            "averagePPA.passingDowns": "avg_ppa_passing_downs",
2047            "totalPPA.all": "total_ppa_all",
2048            "totalPPA.pass": "total_ppa_pass",
2049            "totalPPA.rush": "total_ppa_rush",
2050            "totalPPA.firstDown": "total_ppa_first_down",
2051            "totalPPA.secondDown": "total_ppa_second_down",
2052            "totalPPA.thirdDown": "total_ppa_third_down",
2053            "totalPPA.standardDowns": "total_ppa_standard_downs",
2054            "totalPPA.passingDowns": "total_ppa_passing_downs",
2055        },
2056        inplace=True,
2057    )
2058    return cfb_games_df
2059
2060
2061def get_cfbd_game_win_probability_data(
2062    game_id: int,
2063    api_key: str = None,
2064    api_key_dir: str = None,
2065    return_as_dict: bool = False,
2066):
2067    """
2068    Allows one to get win probability data for a given game ID.
2069
2070    Parameters
2071    ----------
2072
2073    `game_id` (int, mandatory):
2074        Mandatory argument.
2075        This is the game ID for the game you want win probability data from,
2076        at the play-by-play level.
2077
2078    `api_key` (str, optional):
2079        Semi-optional argument.
2080        If `api_key` is null, this function will attempt to load a CFBD API key
2081        from the python environment, or from a file on this computer.
2082        If `api_key` is not null,
2083        this function will automatically assume that the
2084        inputted `api_key` is a valid CFBD API key.
2085
2086    `api_key_dir` (str, optional):
2087        Optional argument.
2088        If `api_key` is set to am empty string, this variable is ignored.
2089        If `api_key_dir` is null, and `api_key` is null,
2090        this function will try to find
2091        a CFBD API key file in this user's home directory.
2092        If `api_key_dir` is set to a string, and `api_key` is null,
2093        this function will assume that `api_key_dir` is a directory,
2094        and will try to find a CFBD API key file in that directory.
2095
2096    `return_as_dict` (bool, semi-optional):
2097        Semi-optional argument.
2098        If you want this function to return
2099        the data as a dictionary (read: JSON object),
2100        instead of a pandas `DataFrame` object,
2101        set `return_as_dict` to `True`.
2102
2103    Usage
2104    ----------
2105    ```
2106    import time
2107
2108    from cfbd_json_py.metrics import get_cfbd_game_win_probability_data
2109
2110
2111    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2112
2113    if cfbd_key != "tigersAreAwesome":
2114        print(
2115            "Using the user's API key declared in this script " +
2116            "for this example."
2117        )
2118
2119        # Get the win probability data for a 2017 game between
2120        # the University of Cincinnati and UConn (game ID #400941851).
2121        print(
2122            "Get the win probability data for a 2017 game between " +
2123            "the University of Cincinnati and UConn (game ID #400941851)."
2124        )
2125        json_data = get_cfbd_game_win_probability_data(
2126            api_key=cfbd_key,
2127            game_id=400941851
2128        )
2129        print(json_data)
2130        time.sleep(5)
2131
2132        # Get the win probability data for a 2023 game between
2133        # the University of Duke and
2134        # the University of Louisville (game ID #401525535).
2135        print(
2136            "Get the win probability data for a 2023 game between " +
2137            "the University of Duke and " +
2138            "the University of Louisville (game ID #401525535)."
2139        )
2140        json_data = get_cfbd_game_win_probability_data(
2141            api_key=cfbd_key,
2142            game_id=401525535
2143        )
2144        print(json_data)
2145        time.sleep(5)
2146
2147
2148        # You can also tell this function to just return the API call as
2149        # a Dictionary (read: JSON) object.
2150        print(
2151            "You can also tell this function to just return the API call " +
2152            "as a Dictionary (read: JSON) object."
2153        )
2154        json_data = get_cfbd_game_win_probability_data(
2155            api_key=cfbd_key,
2156            game_id=400941851,
2157            return_as_dict=True
2158        )
2159        print(json_data)
2160
2161    else:
2162        # Alternatively, if the CFBD API key exists in this python environment,
2163        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2164        # you could just call these functions directly,
2165        # without setting the API key in the script.
2166        print(
2167            "Using the user's API key supposedly loaded into " +
2168            "this python environment for this example."
2169        )
2170
2171        # Get win probability data for a 2017 game between
2172        # the University of Cincinnati and UConn (game ID #400941851).
2173        print(
2174            "Get the win probability data for a 2017 game between " +
2175            "the University of Cincinnati and UConn (game ID #400941851)."
2176        )
2177        json_data = get_cfbd_game_win_probability_data(
2178            game_id=400941851
2179        )
2180        print(json_data)
2181        time.sleep(5)
2182
2183        # Get win probability data for a 2023 game between
2184        # the University of Duke and
2185        # the University of Louisville (game ID #401525535).
2186        print(
2187            "Get the win probability data for a 2023 game between " +
2188            "the University of Duke and " +
2189            "the University of Louisville (game ID #401525535)."
2190        )
2191        json_data = get_cfbd_game_win_probability_data(
2192            game_id=401525535
2193        )
2194        print(json_data)
2195        time.sleep(5)
2196
2197
2198        # You can also tell this function to just return the API call as
2199        # a Dictionary (read: JSON) object.
2200        print(
2201            "You can also tell this function to just return " +
2202            "the API call as a Dictionary (read: JSON) object."
2203        )
2204        json_data = get_cfbd_game_win_probability_data(
2205            game_id=400941851,
2206            return_as_dict=True
2207        )
2208        print(json_data)
2209
2210    ```
2211    Returns
2212    ----------
2213    A pandas `DataFrame` object with win probability data
2214    at the play-by-play level,
2215    or (if `return_as_dict` is set to `True`)
2216    a dictionary object with win probability data at the play-by-play level.
2217
2218    """
2219
2220    wp_df = pd.DataFrame()
2221    # row_df = pd.DataFrame()
2222    url = "https://api.collegefootballdata.com/metrics/wp"
2223
2224    ##########################################################################
2225
2226    if api_key is not None:
2227        real_api_key = api_key
2228        del api_key
2229    else:
2230        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2231
2232    if real_api_key == "tigersAreAwesome":
2233        raise ValueError(
2234            "You actually need to change `cfbd_key` to your CFBD API key."
2235        )
2236    elif "Bearer " in real_api_key:
2237        pass
2238    elif "Bearer" in real_api_key:
2239        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2240    else:
2241        real_api_key = "Bearer " + real_api_key
2242    # URL builder
2243    ##########################################################################
2244
2245    # Required by API
2246    url += f"?gameId={game_id}"
2247
2248    headers = {
2249        "Authorization": f"{real_api_key}", "accept": "application/json"
2250    }
2251
2252    response = requests.get(url, headers=headers)
2253
2254    if response.status_code == 200:
2255        pass
2256    elif response.status_code == 401:
2257        raise ConnectionRefusedError(
2258            "Could not connect. The connection was refused.\n" +
2259            "HTTP Status Code 401."
2260        )
2261    else:
2262        raise ConnectionError(
2263            f"Could not connect.\nHTTP Status code {response.status_code}"
2264        )
2265
2266    json_data = response.json()
2267
2268    if return_as_dict is True:
2269        return json_data
2270
2271    wp_df = pd.json_normalize(json_data)
2272    wp_df.rename(
2273        columns={
2274            "playId": "play_id",
2275            "playText": "play_text",
2276            "homeId": "home_team_id",
2277            "home": "home_team_name",
2278            "awayId": "away_team_id",
2279            "away": "away_team_name",
2280            "spread": "spread_line",
2281            "homeBall": "home_team_on_offense_flag",
2282            "homeScore": "home_score",
2283            "awayScore": "away_score",
2284            "homeWinProb": "home_win_probability",
2285            "playNumber": "play_num",
2286            "yardLine": "yard_line",
2287        },
2288        inplace=True,
2289    )
2290    if len(wp_df) == 0:
2291        logging.error(
2292            "The CFBD API accepted your inputs, "
2293            + "but found no data within your specified input parameters."
2294            + " Please double check your input parameters."
2295        )
2296    else:
2297        wp_df = wp_df.astype({"home_win_probability": "float"})
2298        wp_df["away_win_probability"] = 1 - wp_df["home_win_probability"]
2299
2300    return wp_df
2301
2302
2303def get_cfbd_pregame_win_probability_data(
2304    season: int,
2305    api_key: str = None,
2306    api_key_dir: str = None,
2307    week: int = None,
2308    team: str = None,
2309    season_type: str = "regular",  # "regular" or "postseason"
2310    return_as_dict: bool = False,
2311):
2312    """
2313    Allows you to get pregame win probability data
2314    for games within a time frame.
2315
2316    Parameters
2317    ----------
2318    `api_key` (str, optional):
2319        Semi-optional argument.
2320        If `api_key` is null, this function will attempt to load a CFBD API key
2321        from the python environment, or from a file on this computer.
2322        If `api_key` is not null,
2323        this function will automatically assume that the
2324        inputted `api_key` is a valid CFBD API key.
2325
2326    `api_key_dir` (str, optional):
2327        Optional argument.
2328        If `api_key` is set to am empty string, this variable is ignored.
2329        If `api_key_dir` is null, and `api_key` is null,
2330        this function will try to find
2331        a CFBD API key file in this user's home directory.
2332        If `api_key_dir` is set to a string, and `api_key` is null,
2333        this function will assume that `api_key_dir` is a directory,
2334        and will try to find a CFBD API key file in that directory.
2335
2336    `season` (int, optional):
2337        Semi-optional argument.
2338        Specifies the season you want pregame win probability data.
2339
2340    `week` (int, optional):
2341        Optional argument.
2342        If `week` is set to an integer, this function will attempt
2343        to load CFB game data from games in that season, and in that week.
2344
2345    `team` (str, optional):
2346        Semi-optional argument.
2347        If you only want pregame win probability data for a specific team,
2348        set `team` to the name of the team
2349        you want pregame win probability data from.
2350
2351    `season_type` (str, semi-optional):
2352        Semi-optional argument.
2353        By default, this will be set to "regular", for the CFB regular season.
2354        If you want CFB game information for non-regular season games,
2355        set `season_type` to "postseason".
2356        If `season_type` is set to anything but "regular" or "postseason",
2357        a `ValueError()` will be raised.
2358
2359    `return_as_dict` (bool, semi-optional):
2360        Semi-optional argument.
2361        If you want this function to return the data
2362        as a dictionary (read: JSON object),
2363        instead of a pandas `DataFrame` object,
2364        set `return_as_dict` to `True`.
2365
2366    Usage
2367    ----------
2368    ```
2369    import time
2370
2371    from cfbd_json_py.metrics import get_cfbd_pregame_win_probability_data
2372
2373
2374    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2375
2376    if cfbd_key != "tigersAreAwesome":
2377        print(
2378            "Using the user's API key declared in this script " +
2379            "for this example."
2380        )
2381
2382        # Get pregame win probabilities for games in the 2023 CFB season.
2383        print(
2384            "Get pregame win probabilities for games in the 2023 CFB season."
2385        )
2386        json_data = get_cfbd_pregame_win_probability_data(
2387            api_key=cfbd_key,
2388            season=2023
2389        )
2390        print(json_data)
2391        time.sleep(5)
2392
2393        # Get pregame win probabilities for games
2394        # in week 10 of the 2021 CFB season.
2395        print(
2396            "Get pregame win probabilities for games " +
2397            "in week 10 of the 2021 CFB season."
2398        )
2399        json_data = get_cfbd_pregame_win_probability_data(
2400            api_key=cfbd_key,
2401            season=2021,
2402            week=10
2403        )
2404        print(json_data)
2405        time.sleep(5)
2406
2407
2408        # Get pregame win probabilities for games involving
2409        # the 2021 Cincinnati Bearcats Football Team.
2410        print(
2411            "Get pregame win probabilities for games involving " +
2412            "the 2021 Cincinnati Bearcats Football Team."
2413        )
2414        json_data = get_cfbd_pregame_win_probability_data(
2415            api_key=cfbd_key,
2416            season=2021,
2417            week=10
2418        )
2419        print(json_data)
2420        time.sleep(5)
2421
2422        # Get pregame win probabilities for postseason games
2423        # in the 2020 CFB season.
2424        print(
2425            "Get pregame win probabilities for postseason games " +
2426            "in the 2020 CFB season."
2427        )
2428        json_data = get_cfbd_pregame_win_probability_data(
2429            api_key=cfbd_key,
2430            season=2020,
2431            season_type="postseason"
2432        )
2433        print(json_data)
2434        time.sleep(5)
2435
2436
2437        # You can also tell this function to just return the API call as
2438        # a Dictionary (read: JSON) object.
2439        print(
2440            "You can also tell this function to just return the API call " +
2441            "as a Dictionary (read: JSON) object."
2442        )
2443        json_data = get_cfbd_pregame_win_probability_data(
2444            api_key=cfbd_key,
2445            season=2023,
2446            week=10,
2447            return_as_dict=True
2448        )
2449        print(json_data)
2450
2451    else:
2452        # Alternatively, if the CFBD API key exists in this python environment,
2453        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2454        # you could just call these functions directly,
2455        # without setting the API key in the script.
2456        print(
2457            "Using the user's API key supposedly loaded " +
2458            "into this python environment for this example."
2459        )
2460
2461    # Get pregame win probabilities for games in the 2023 CFB season.
2462        print(
2463            "Get pregame win probabilities for games in the 2023 CFB season."
2464        )
2465        json_data = get_cfbd_pregame_win_probability_data(
2466            season=2023
2467        )
2468        print(json_data)
2469        time.sleep(5)
2470
2471
2472        # Get pregame win probabilities for games
2473        # in week 10 of the 2021 CFB season.
2474        print(
2475            "Get pregame win probabilities for games " +
2476            "in week 10 of the 2021 CFB season."
2477        )
2478        json_data = get_cfbd_pregame_win_probability_data(
2479            season=2021,
2480            week=10
2481        )
2482        print(json_data)
2483        time.sleep(5)
2484
2485
2486        # Get pregame win probabilities for games involving
2487        # the 2021 Cincinnati Bearcats Football Team.
2488        print(
2489            "Get pregame win probabilities for games involving " +
2490            "the 2021 Cincinnati Bearcats Football Team."
2491        )
2492        json_data = get_cfbd_pregame_win_probability_data(
2493            season=2021,
2494            week=10
2495        )
2496        print(json_data)
2497        time.sleep(5)
2498
2499
2500        # Get pregame win probabilities for postseason games
2501        # in the 2020 CFB season.
2502        print(
2503            "Get pregame win probabilities for postseason games" +
2504            " in the 2020 CFB season."
2505        )
2506        json_data = get_cfbd_pregame_win_probability_data(
2507            season=2020,
2508            season_type="postseason"
2509        )
2510        print(json_data)
2511        time.sleep(5)
2512
2513        # You can also tell this function to just return the API call as
2514        # a Dictionary (read: JSON) object.
2515        print(
2516            "You can also tell this function to just return the API call " +
2517            "as a Dictionary (read: JSON) object."
2518        )
2519        json_data = get_cfbd_pregame_win_probability_data(
2520            season=2023,
2521            week=10,
2522            return_as_dict=True
2523        )
2524        print(json_data)
2525
2526    ```
2527    Returns
2528    ----------
2529    A pandas `DataFrame` object with pregame win probability data,
2530    or (if `return_as_dict` is set to `True`)
2531    a dictionary object with a pregame win probability data.
2532
2533    """
2534    now = datetime.now()
2535    wp_df = pd.DataFrame()
2536    # row_df = pd.DataFrame()
2537    url = "https://api.collegefootballdata.com/metrics/wp/pregame"
2538
2539    ##########################################################################
2540
2541    if api_key is not None:
2542        real_api_key = api_key
2543        del api_key
2544    else:
2545        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2546
2547    if real_api_key == "tigersAreAwesome":
2548        raise ValueError(
2549            "You actually need to change `cfbd_key` to your CFBD API key."
2550        )
2551    elif "Bearer " in real_api_key:
2552        pass
2553    elif "Bearer" in real_api_key:
2554        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2555    else:
2556        real_api_key = "Bearer " + real_api_key
2557
2558    if season is None:
2559        pass
2560    elif season > (now.year + 1):
2561        raise ValueError(f"`season` cannot be greater than {season}.")
2562    elif season < 1869:
2563        raise ValueError("`season` cannot be less than 1869.")
2564
2565    if week is not None and week < 0:
2566        raise ValueError("`week` must be an integer greater than 0.")
2567
2568    if season_type != "regular" and season_type != "postseason":
2569        raise ValueError(
2570            '`season_type` must be set to either ' +
2571            '"regular" or "postseason" for this function to work.'
2572        )
2573
2574    # URL builder
2575    ##########################################################################
2576
2577    url_elements = 0
2578
2579    if season is not None and url_elements == 0:
2580        url += f"?year={season}"
2581        url_elements += 1
2582    elif season is not None:
2583        url += f"&year={season}"
2584        url_elements += 1
2585
2586    if week is not None and url_elements == 0:
2587        url += f"?week={week}"
2588        url_elements += 1
2589    elif week is not None:
2590        url += f"&week={week}"
2591        url_elements += 1
2592
2593    if team is not None and url_elements == 0:
2594        url += f"?team={team}"
2595        url_elements += 1
2596    elif team is not None:
2597        url += f"&team={team}"
2598        url_elements += 1
2599
2600    if season_type is not None and url_elements == 0:
2601        url += f"?seasonType={season_type}"
2602        url_elements += 1
2603    elif season_type is not None:
2604        url += f"&seasonType={season_type}"
2605        url_elements += 1
2606
2607    headers = {
2608        "Authorization": f"{real_api_key}", "accept": "application/json"
2609    }
2610
2611    response = requests.get(url, headers=headers)
2612
2613    if response.status_code == 200:
2614        pass
2615    elif response.status_code == 401:
2616        raise ConnectionRefusedError(
2617            "Could not connect. The connection was refused.\n" +
2618            "HTTP Status Code 401."
2619        )
2620    else:
2621        raise ConnectionError(
2622            f"Could not connect.\nHTTP Status code {response.status_code}"
2623        )
2624
2625    json_data = response.json()
2626
2627    if return_as_dict is True:
2628        return json_data
2629
2630    wp_df = pd.json_normalize(json_data)
2631    wp_df.rename(
2632        columns={
2633            "seasonType": "season_type",
2634            "gameId": "game_id",
2635            "homeTeam": "home_team_name",
2636            "awayTeam": "away_team_name",
2637            "spread": "spread_line",
2638            "homeWinProb": "home_win_probability",
2639        },
2640        inplace=True,
2641    )
2642    if len(wp_df) == 0:
2643        logging.error(
2644            "The CFBD API accepted your inputs, "
2645            + "but found no data within your specified input parameters."
2646            + " Please double check your input parameters."
2647        )
2648    else:
2649        wp_df = wp_df.astype({"home_win_probability": "float"})
2650        wp_df["away_win_probability"] = 1 - wp_df["home_win_probability"]
2651
2652    return wp_df
2653
2654
2655def get_cfbd_fg_expected_points(
2656    api_key: str = None, api_key_dir: str = None, return_as_dict: bool = False
2657):
2658    """
2659    Retrieves Expected Points data for field goals from the CFBD API.
2660
2661    Parameters
2662    ----------
2663    `api_key` (str, optional):
2664        Semi-optional argument.
2665        If `api_key` is null, this function will attempt to load a CFBD API key
2666        from the python environment, or from a file on this computer.
2667        If `api_key` is not null,
2668        this function will automatically assume that the
2669        inputted `api_key` is a valid CFBD API key.
2670
2671    `api_key_dir` (str, optional):
2672        Optional argument.
2673        If `api_key` is set to am empty string, this variable is ignored.
2674        If `api_key_dir` is null, and `api_key` is null,
2675        this function will try to find
2676        a CFBD API key file in this user's home directory.
2677        If `api_key_dir` is set to a string, and `api_key` is null,
2678        this function will assume that `api_key_dir` is a directory,
2679        and will try to find a CFBD API key file in that directory.
2680
2681    `return_as_dict` (bool, semi-optional):
2682        Semi-optional argument.
2683        If you want this function to return the data
2684        as a dictionary (read: JSON object),
2685        instead of a pandas `DataFrame` object,
2686        set `return_as_dict` to `True`.
2687
2688    Usage
2689    ----------
2690    ```
2691    import time
2692
2693    from cfbd_json_py.metrics import get_cfbd_fg_expected_points
2694
2695
2696    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2697
2698    if cfbd_key != "tigersAreAwesome":
2699        print(
2700            "Using the user's API key declared in this script " +
2701            "for this example."
2702        )
2703
2704        # Get Expected Points (EP) data, specifically for field goals,
2705        # from the CFBD API.
2706        print(
2707            "Get Expected Points (EP) data, specifically for " +
2708            "field goals, from the CFBD API."
2709        )
2710        json_data = get_cfbd_fg_expected_points(
2711            api_key=cfbd_key,
2712        )
2713        print(json_data)
2714        time.sleep(5)
2715
2716
2717        # You can also tell this function to just return the API call as
2718        # a Dictionary (read: JSON) object.
2719        print(
2720            "You can also tell this function to just return the API call " +
2721            "as a Dictionary (read: JSON) object."
2722        )
2723        json_data = get_cfbd_fg_expected_points(
2724            api_key=cfbd_key,
2725            return_as_dict=True
2726        )
2727        print(json_data)
2728
2729    else:
2730        # Alternatively, if the CFBD API key exists in this python environment,
2731        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2732        # you could just call these functions directly,
2733        # without setting the API key in the script.
2734        print(
2735            "Using the user's API key supposedly loaded " +
2736            "into this python environment for this example."
2737        )
2738
2739        # Get Expected Points (EP) data,
2740        # specifically for field goals, from the CFBD API.
2741        print(
2742            "Get Expected Points (EP) data, " +
2743            "specifically for field goals, from the CFBD API."
2744        )
2745        json_data = get_cfbd_fg_expected_points()
2746        print(json_data)
2747        time.sleep(5)
2748
2749
2750        # You can also tell this function to just return the API call as
2751        # a Dictionary (read: JSON) object.
2752        print(
2753            "You can also tell this function to just return the API call " +
2754            "as a Dictionary (read: JSON) object."
2755        )
2756        json_data = get_cfbd_fg_expected_points(
2757            return_as_dict=True
2758        )
2759        print(json_data)
2760    ```
2761
2762    Returns
2763    ----------
2764    A pandas `DataFrame` object with Expected Points data for field goals,
2765    or (if `return_as_dict` is set to `True`)
2766    a dictionary object with Expected Points data for field goals.
2767
2768    """
2769    epa_df = pd.DataFrame()
2770    # row_df = pd.DataFrame()
2771    url = "https://api.collegefootballdata.com/metrics/fg/ep"
2772
2773    # Input validation
2774    ##########################################################################
2775
2776    if api_key is not None:
2777        real_api_key = api_key
2778        del api_key
2779    else:
2780        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2781
2782    if real_api_key == "tigersAreAwesome":
2783        raise ValueError(
2784            "You actually need to change `cfbd_key` to your CFBD API key."
2785        )
2786    elif "Bearer " in real_api_key:
2787        pass
2788    elif "Bearer" in real_api_key:
2789        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2790    else:
2791        real_api_key = "Bearer " + real_api_key
2792
2793    headers = {
2794        "Authorization": f"{real_api_key}", "accept": "application/json"
2795    }
2796
2797    response = requests.get(url, headers=headers)
2798
2799    if response.status_code == 200:
2800        pass
2801    elif response.status_code == 401:
2802        raise ConnectionRefusedError(
2803            "Could not connect. The connection was refused.\n" +
2804            "HTTP Status Code 401."
2805        )
2806    else:
2807        raise ConnectionError(
2808            f"Could not connect.\nHTTP Status code {response.status_code}"
2809        )
2810
2811    json_data = response.json()
2812
2813    if return_as_dict is True:
2814        return json_data
2815
2816    epa_df = pd.json_normalize(json_data)
2817    epa_df.rename(
2818        columns={
2819            "yardsToGoal": "yards_to_goal",
2820            "expectedPoints": "expected_points",
2821        },
2822        inplace=True,
2823    )
2824    return epa_df
def get_cfbd_predicted_ppa_from_down_distance( down: int, distance: int, api_key: str = None, api_key_dir: str = None, return_as_dict: bool = False):
 19def get_cfbd_predicted_ppa_from_down_distance(
 20    down: int,
 21    distance: int,
 22    api_key: str = None,
 23    api_key_dir: str = None,
 24    return_as_dict: bool = False,
 25):
 26    """
 27    Given a down and distance,
 28    this function will attempt to get the predicted
 29    PPA value for that down and distance,
 30    at every yard line possible for that down and distance.
 31
 32    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
 33
 34    For this endpoint,
 35    [`yardLine`] is the number of yards from 1
 36    (offense has the ball on their side,at their 1 yard line),
 37    to 99 (offense with the ball with a X and goal situation
 38    on the opponent's 1 yard line.
 39
 40    Parameters
 41    ----------
 42    `down` (int, mandatory):
 43        Mandatory argument.
 44        This is the down (a number between 1 and 4 in normal situations)
 45        for this play you want PPA for.
 46
 47    `distance` (int, mandatory):
 48        Mandatory argument.
 49        This variable should be set to the number of yards between
 50        the line of scrimmage (LOS), and the first down line on the field.
 51
 52    `api_key` (str, optional):
 53        Semi-optional argument.
 54        If `api_key` is null, this function will attempt to load a CFBD API key
 55        from the python environment, or from a file on this computer.
 56        If `api_key` is not null,
 57        this function will automatically assume that the
 58        inputted `api_key` is a valid CFBD API key.
 59
 60    `api_key_dir` (str, optional):
 61        Optional argument.
 62        If `api_key` is set to am empty string, this variable is ignored.
 63        If `api_key_dir` is null, and `api_key` is null,
 64        this function will try to find
 65        a CFBD API key file in this user's home directory.
 66        If `api_key_dir` is set to a string, and `api_key` is null,
 67        this function will assume that `api_key_dir` is a directory,
 68        and will try to find a CFBD API key file in that directory.
 69
 70    `return_as_dict` (bool, semi-optional):
 71        Semi-optional argument.
 72        If you want this function to return the data as a dictionary
 73        (read: JSON object), instead of a pandas `DataFrame` object,
 74        set `return_as_dict` to `True`.
 75
 76    Usage
 77    ----------
 78    ```
 79    import time
 80
 81    from cfbd_json_py.metrics import get_cfbd_predicted_ppa_from_down_distance
 82
 83
 84    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
 85
 86    if cfbd_key != "tigersAreAwesome":
 87        print(
 88            "Using the user's API key declared " +
 89            "in this script for this example."
 90        )
 91
 92        # Get the predicted PPA for a 1st and 10 play,
 93        # in every possible situation.
 94        print(
 95            "Get the predicted PPA for a 1st and 10 play, " +
 96            "in every possible situation."
 97        )
 98        json_data = get_cfbd_predicted_ppa_from_down_distance(
 99            down=1,
100            distance=10,
101            api_key=cfbd_key
102        )
103        print(json_data)
104        time.sleep(5)
105
106
107        # You can also tell this function to just return the API call as
108        # a Dictionary (read: JSON) object.
109        print(
110            "You can also tell this function to just return the API call " +
111            "as a Dictionary (read: JSON) object."
112        )
113        json_data = get_cfbd_predicted_ppa_from_down_distance(
114            down=1,
115            distance=10,
116            api_key=cfbd_key,
117            return_as_dict=True
118        )
119        print(json_data)
120
121    else:
122        # Alternatively, if the CFBD API key exists in this python environment,
123        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
124        # you could just call these functions directly,
125        # without setting the API key in the script.
126        print(
127            "Using the user's API key supposedly loaded " +
128            "into this python environment for this example."
129        )
130
131
132        # Get the predicted PPA for a 1st and 10 play,
133        # in every possible situation.
134        print(
135            "Get the predicted PPA for a 1st and 10 play, " +
136            "in every possible situation."
137        )
138        json_data = get_cfbd_predicted_ppa_from_down_distance(
139            down=1,
140            distance=10
141        )
142        print(json_data)
143        time.sleep(5)
144
145
146        # You can also tell this function to just return the API call as
147        # a Dictionary (read: JSON) object.
148        print(
149            "You can also tell this function to just return the API call " +
150            "as a Dictionary (read: JSON) object."
151        )
152        json_data = get_cfbd_predicted_ppa_from_down_distance(
153            down=1,
154            distance=10,
155            return_as_dict=True
156        )
157        print(json_data)
158
159    ```
160    Returns
161    ----------
162    A pandas `DataFrame` object with a calculated PPA from a down and distance,
163    or (if `return_as_dict` is set to `True`)
164    a dictionary object with a calculated PPA from a down and distance.
165
166
167    """
168
169    ppa_df = pd.DataFrame()
170    url = "https://api.collegefootballdata.com/ppa/predicted"
171
172    ##########################################################################
173
174    if api_key is not None:
175        real_api_key = api_key
176        del api_key
177    else:
178        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
179
180    if real_api_key == "tigersAreAwesome":
181        raise ValueError(
182            "You actually need to change `cfbd_key` to your CFBD API key."
183        )
184    elif "Bearer " in real_api_key:
185        pass
186    elif "Bearer" in real_api_key:
187        real_api_key = real_api_key.replace("Bearer", "Bearer ")
188    else:
189        real_api_key = "Bearer " + real_api_key
190
191    if down >= 1 and down <= 4:
192        # This is normal, so pass.
193        pass
194    elif down == 5:
195        # Due to a Missouri-Colorado game in the 90s
196        # being won by Colorado on a mythical "5th down",
197        # we cannot reject this down outright,
198        # but we have to convey to the person calling this
199        # function that setting `down = 5`
200        # is not something they should be doing.
201        logging.warning(
202            'There is a very limited number of "5th down" situations '
203            + "in American Football history. "
204            + "Do not expect anything back when calling this function, "
205            + "and setting`down` to `5`."
206        )
207    else:
208        raise ValueError(
209            "Invalid `down` inputted! Valid inputs are:\n"
210            + "\n\t- `1`"
211            + "\n\t- `2`"
212            + "\n\t- `3`"
213            + "\n\t- `4`"
214            + f"\nYou entered: \t`{down}`"
215        )
216
217    if distance == 0:
218        raise ValueError(
219            'If you want "X and inches" predicted PPA data, '
220            + "set `down` to `1` when calling this function."
221        )
222    elif distance >= 100 and distance <= 110:
223        raise ValueError(
224            "The CFBD API cannot calculate predicted PPA for "
225            + "U-Sports (Canada) football."
226        )
227    elif distance >= 1 and distance <= 99:
228        # While numbers beyond 30 are rare,
229        # there are some situations IRL that caused the distance
230        # in "down and distance" to exceed 90
231        # (most famously a 2017 game between
232        # Mississippi State and Louisiana Tech).
233        pass
234
235    # URL builder
236    ##########################################################################
237
238    # Required by API
239    url += f"?down={down}&distance={distance}"
240
241    headers = {
242        "Authorization": f"{real_api_key}", "accept": "application/json"
243    }
244
245    response = requests.get(url, headers=headers)
246
247    if response.status_code == 200:
248        pass
249    elif response.status_code == 401:
250        raise ConnectionRefusedError(
251            "Could not connect. The connection was refused.\n" +
252            "HTTP Status Code 401."
253        )
254    else:
255        raise ConnectionError(
256            f"Could not connect.\nHTTP Status code {response.status_code}"
257        )
258
259    json_data = response.json()
260
261    if return_as_dict is True:
262        return json_data
263
264    ppa_df = pd.json_normalize(json_data)
265    ppa_df.rename(
266        columns={
267            "yardLine": "yard_line",
268            "predictedPoints": "predicted_points"
269        },
270        inplace=True,
271    )
272    return ppa_df

Given a down and distance, this function will attempt to get the predicted PPA value for that down and distance, at every yard line possible for that down and distance.

PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).

For this endpoint, [yardLine] is the number of yards from 1 (offense has the ball on their side,at their 1 yard line), to 99 (offense with the ball with a X and goal situation on the opponent's 1 yard line.

Parameters

down (int, mandatory): Mandatory argument. This is the down (a number between 1 and 4 in normal situations) for this play you want PPA for.

distance (int, mandatory): Mandatory argument. This variable should be set to the number of yards between the line of scrimmage (LOS), and the first down line on the field.

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_predicted_ppa_from_down_distance


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared " +
        "in this script for this example."
    )

    # Get the predicted PPA for a 1st and 10 play,
    # in every possible situation.
    print(
        "Get the predicted PPA for a 1st and 10 play, " +
        "in every possible situation."
    )
    json_data = get_cfbd_predicted_ppa_from_down_distance(
        down=1,
        distance=10,
        api_key=cfbd_key
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_predicted_ppa_from_down_distance(
        down=1,
        distance=10,
        api_key=cfbd_key,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded " +
        "into this python environment for this example."
    )


    # Get the predicted PPA for a 1st and 10 play,
    # in every possible situation.
    print(
        "Get the predicted PPA for a 1st and 10 play, " +
        "in every possible situation."
    )
    json_data = get_cfbd_predicted_ppa_from_down_distance(
        down=1,
        distance=10
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_predicted_ppa_from_down_distance(
        down=1,
        distance=10,
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with a calculated PPA from a down and distance, or (if return_as_dict is set to True) a dictionary object with a calculated PPA from a down and distance.

def get_cfbd_team_season_ppa_data( api_key: str = None, api_key_dir: str = None, season: int = None, team: str = None, conference: str = None, exclude_garbage_time: bool = False, return_as_dict: bool = False):
275def get_cfbd_team_season_ppa_data(
276    api_key: str = None,
277    api_key_dir: str = None,
278    season: int = None,
279    team: str = None,
280    # `year` and/or `team` must be not null for this function to work.
281    conference: str = None,
282    exclude_garbage_time: bool = False,
283    return_as_dict: bool = False,
284):
285    """
286    Allows you to get team PPA data,
287    over an entire season,
288    with or without garbage time plays,
289    for a specified team and/or time period.
290
291    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
292
293    Parameters
294    ----------
295    `api_key` (str, optional):
296        Semi-optional argument.
297        If `api_key` is null, this function will attempt to load a CFBD API key
298        from the python environment, or from a file on this computer.
299        If `api_key` is not null,
300        this function will automatically assume that the
301        inputted `api_key` is a valid CFBD API key.
302
303    `api_key_dir` (str, optional):
304        Optional argument.
305        If `api_key` is set to am empty string, this variable is ignored.
306        If `api_key_dir` is null, and `api_key` is null,
307        this function will try to find
308        a CFBD API key file in this user's home directory.
309        If `api_key_dir` is set to a string, and `api_key` is null,
310        this function will assume that `api_key_dir` is a directory,
311        and will try to find a CFBD API key file in that directory.
312
313    `season` (int, optional):
314        Semi-optional argument.
315        Specifies the season you want team PPA data from.
316        You MUST set `season` or `team` to a non-null value for
317        this function to work. If you don't, a `ValueError()`
318        will be raised.
319
320    `team` (str, optional):
321        Semi-optional argument.
322        If you only want team PPA data for a specific team,
323        set `team` to the name of the team you want team PPA data from.
324        You MUST set `season` or `team` to a non-null value for
325        this function to work. If you don't, a `ValueError()`
326        will be raised.
327
328    `conference` (str, optional):
329        Optional argument.
330        If you only want team PPA data from games
331        involving teams from a specific conference,
332        set `conference` to the abbreviation
333        of the conference you want team PPA data from.
334        For a list of conferences,
335        use the `cfbd_json_py.conferences.get_cfbd_conference_info()`
336        function.
337
338    `exclude_garbage_time` (bool, optional):
339        Optional argument.
340        If you want to filter out plays
341        where the result of the game is largely decided,
342        set `exclude_garbage_time = True`.
343        Default behavior is that this variable is set to
344        `False` when this function is called.
345
346    `return_as_dict` (bool, semi-optional):
347        Semi-optional argument.
348        If you want this function
349        to return the data as a dictionary (read: JSON object),
350        instead of a pandas `DataFrame` object,
351        set `return_as_dict` to `True`.
352
353    Usage
354    ----------
355    ```
356    import time
357
358    from cfbd_json_py.metrics import get_cfbd_team_season_ppa_data
359
360
361    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
362
363    if cfbd_key != "tigersAreAwesome":
364        print(
365            "Using the user's API key declared in this script " +
366            "for this example."
367        )
368
369        # Get team season PPA data for the 2020 CFB season.
370        print("Get team PPA data for the 2020 CFB season.")
371        json_data = get_cfbd_team_season_ppa_data(
372            api_key=cfbd_key,
373            season=2020
374        )
375        print(json_data)
376        time.sleep(5)
377
378        # Get team season PPA data for the 2020 Ohio State Buckeyes.
379        print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
380        json_data = get_cfbd_team_season_ppa_data(
381            api_key=cfbd_key,
382            season=2020,
383            team="Ohio State"
384        )
385        print(json_data)
386        time.sleep(5)
387
388        # Get team season PPA data for the 2020 Ohio State Buckeyes,
389        # but exclude garbage time plays when making the PPA calculations.
390        print(
391            "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
392            "but exclude garbage time plays when making the PPA calculations."
393        )
394        json_data = get_cfbd_team_season_ppa_data(
395            api_key=cfbd_key,
396            season=2020,
397            team="Ohio State",
398            exclude_garbage_time=True
399        )
400        print(json_data)
401        time.sleep(5)
402
403        # Get team season PPA data for teams in the Big 10 (B1G) Conference
404        # in the 2020 CFB Season.
405        print(
406            "Get team season PPA data for teams in the " +
407            "Big 10 (B1G) Conference in the 2020 CFB Season."
408        )
409        json_data = get_cfbd_team_season_ppa_data(
410            api_key=cfbd_key,
411            season=2020,
412            conference="B1G"
413        )
414        print(json_data)
415        time.sleep(5)
416
417        # You can also tell this function to just return the API call as
418        # a Dictionary (read: JSON) object.
419        print(
420            "You can also tell this function to just return the API call " +
421            "as a Dictionary (read: JSON) object."
422        )
423        json_data = get_cfbd_team_season_ppa_data(
424            api_key=cfbd_key,
425            season=2020,
426            conference="B1G",
427            return_as_dict=True
428        )
429        print(json_data)
430
431    else:
432        # Alternatively, if the CFBD API key exists in this python environment,
433        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
434        # you could just call these functions directly,
435        # without setting the API key in the script.
436        print(
437            "Using the user's API key supposedly loaded into " +
438            "this python environment for this example."
439        )
440
441        # Get team season PPA data for the 2020 CFB season.
442        print("Get team PPA data for the 2020 CFB season.")
443        json_data = get_cfbd_team_season_ppa_data(
444            season=2020
445        )
446        print(json_data)
447        time.sleep(5)
448
449        # Get team season PPA data for the 2020 Ohio State Buckeyes.
450        print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
451        json_data = get_cfbd_team_season_ppa_data(
452            season=2020,
453            team="Ohio State"
454        )
455        print(json_data)
456        time.sleep(5)
457
458        # Get team season PPA data for the 2020 Ohio State Buckeyes,
459        # but exclude garbage time plays when making the PPA calculations.
460        print(
461            "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
462            "but exclude garbage time plays when making the PPA calculations."
463        )
464        json_data = get_cfbd_team_season_ppa_data(
465            season=2020,
466            team="Ohio State",
467            exclude_garbage_time=True
468        )
469        print(json_data)
470        time.sleep(5)
471
472        # Get team season PPA data for teams in
473        # the Big 10 (B1G) Conference in the 2020 CFB Season.
474        print(
475            "Get team season PPA data for teams in " +
476            "the Big 10 (B1G) Conference in the 2020 CFB Season."
477        )
478        json_data = get_cfbd_team_season_ppa_data(
479            season=2020,
480            conference="B1G"
481        )
482        print(json_data)
483        time.sleep(5)
484
485        # You can also tell this function to just return the API call as
486        # a Dictionary (read: JSON) object.
487        print(
488            "You can also tell this function to just return the API call " +
489            "as a Dictionary (read: JSON) object."
490        )
491        json_data = get_cfbd_team_season_ppa_data(
492            season=2020,
493            conference="B1G",
494            return_as_dict=True
495        )
496        print(json_data)
497
498    ```
499    Returns
500    ----------
501    A pandas `DataFrame` object with team season PPA data,
502    or (if `return_as_dict` is set to `True`)
503    a dictionary object with a team season PPA data.
504
505    """
506
507    now = datetime.now()
508    ppa_df = pd.DataFrame()
509    # row_df = pd.DataFrame()
510    url = "https://api.collegefootballdata.com/ppa/teams"
511
512    ##########################################################################
513
514    if api_key is not None:
515        real_api_key = api_key
516        del api_key
517    else:
518        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
519
520    if real_api_key == "tigersAreAwesome":
521        raise ValueError(
522            "You actually need to change `cfbd_key` to your CFBD API key."
523        )
524    elif "Bearer " in real_api_key:
525        pass
526    elif "Bearer" in real_api_key:
527        real_api_key = real_api_key.replace("Bearer", "Bearer ")
528    else:
529        real_api_key = "Bearer " + real_api_key
530
531    if season is None and team is None:
532        raise ValueError(
533            "To use this function, `season` and/or `team` must be set to a "
534            + "non-null variable."
535        )
536
537    if season is None:
538        # Rare, but in this endpoint,
539        # you don't need to input the season.
540        pass
541    elif season > (now.year + 1):
542        raise ValueError(f"`season` cannot be greater than {season}.")
543    elif season < 1869:
544        raise ValueError("`season` cannot be less than 1869.")
545
546    gt_str = ""
547    if exclude_garbage_time is True:
548        gt_str = "true"
549    elif exclude_garbage_time is False:
550        gt_str = "false"
551
552    # URL builder
553    ##########################################################################
554
555    url_elements = 0
556
557    if season is not None and url_elements == 0:
558        url += f"?year={season}"
559        url_elements += 1
560    elif season is not None:
561        url += f"&year={season}"
562        url_elements += 1
563
564    if team is not None and url_elements == 0:
565        url += f"?team={team}"
566        url_elements += 1
567    elif team is not None:
568        url += f"&team={team}"
569        url_elements += 1
570
571    if conference is not None and url_elements == 0:
572        url += f"?conference={conference}"
573        url_elements += 1
574    elif conference is not None:
575        url += f"&conference={conference}"
576        url_elements += 1
577
578    if exclude_garbage_time is not None and url_elements == 0:
579        url += f"?excludeGarbageTime={gt_str}"
580        url_elements += 1
581    elif exclude_garbage_time is not None:
582        url += f"&excludeGarbageTime={gt_str}"
583        url_elements += 1
584
585    headers = {
586        "Authorization": f"{real_api_key}", "accept": "application/json"
587    }
588
589    response = requests.get(url, headers=headers)
590
591    if response.status_code == 200:
592        pass
593    elif response.status_code == 401:
594        raise ConnectionRefusedError(
595            "Could not connect. The connection was refused.\n" +
596            "HTTP Status Code 401."
597        )
598    else:
599        raise ConnectionError(
600            f"Could not connect.\nHTTP Status code {response.status_code}"
601        )
602
603    json_data = response.json()
604
605    if return_as_dict is True:
606        return json_data
607
608    ppa_df = pd.json_normalize(json_data)
609    # print(ppa_df.columns)
610    ppa_df.rename(
611        columns={
612            "conference": "conference_name",
613            "team": "team_name",
614            "offense.overall": "ppa_offense_overall",
615            "offense.passing": "ppa_offense_passing",
616            "offense.rushing": "ppa_offense_rushing",
617            "offense.firstDown": "ppa_offense_first_down",
618            "offense.secondDown": "ppa_offense_second_down",
619            "offense.thirdDown": "ppa_offense_third_down",
620            "offense.cumulative.total": "ppa_offense_cumulative_total",
621            "offense.cumulative.passing": "ppa_offense_cumulative_passing",
622            "offense.cumulative.rushing": "ppa_offense_cumulative_rushing",
623            "defense.overall": "ppa_defense_overall",
624            "defense.passing": "ppa_defense_passing",
625            "defense.rushing": "ppa_defense_rushing",
626            "defense.firstDown": "ppa_defense_first_down",
627            "defense.secondDown": "ppa_defense_second_down",
628            "defense.thirdDown": "ppa_defense_third_down",
629            "defense.cumulative.total": "ppa_defense_cumulative_total",
630            "defense.cumulative.passing": "ppa_defense_cumulative_passing",
631            "defense.cumulative.rushing": "ppa_defense_cumulative_rushing",
632        },
633        inplace=True,
634    )
635    return ppa_df

Allows you to get team PPA data, over an entire season, with or without garbage time plays, for a specified team and/or time period.

PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).

Parameters

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

season (int, optional): Semi-optional argument. Specifies the season you want team PPA data from. You MUST set season or team to a non-null value for this function to work. If you don't, a ValueError() will be raised.

team (str, optional): Semi-optional argument. If you only want team PPA data for a specific team, set team to the name of the team you want team PPA data from. You MUST set season or team to a non-null value for this function to work. If you don't, a ValueError() will be raised.

conference (str, optional): Optional argument. If you only want team PPA data from games involving teams from a specific conference, set conference to the abbreviation of the conference you want team PPA data from. For a list of conferences, use the cfbd_json_py.conferences.get_cfbd_conference_info() function.

exclude_garbage_time (bool, optional): Optional argument. If you want to filter out plays where the result of the game is largely decided, set exclude_garbage_time = True. Default behavior is that this variable is set to False when this function is called.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_team_season_ppa_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get team season PPA data for the 2020 CFB season.
    print("Get team PPA data for the 2020 CFB season.")
    json_data = get_cfbd_team_season_ppa_data(
        api_key=cfbd_key,
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for the 2020 Ohio State Buckeyes.
    print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
    json_data = get_cfbd_team_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Ohio State"
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for the 2020 Ohio State Buckeyes,
    # but exclude garbage time plays when making the PPA calculations.
    print(
        "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
        "but exclude garbage time plays when making the PPA calculations."
    )
    json_data = get_cfbd_team_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Ohio State",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for teams in the Big 10 (B1G) Conference
    # in the 2020 CFB Season.
    print(
        "Get team season PPA data for teams in the " +
        "Big 10 (B1G) Conference in the 2020 CFB Season."
    )
    json_data = get_cfbd_team_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        conference="B1G"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_team_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        conference="B1G",
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded into " +
        "this python environment for this example."
    )

    # Get team season PPA data for the 2020 CFB season.
    print("Get team PPA data for the 2020 CFB season.")
    json_data = get_cfbd_team_season_ppa_data(
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for the 2020 Ohio State Buckeyes.
    print("Get team season PPA data for the 2020 Ohio State Buckeyes.")
    json_data = get_cfbd_team_season_ppa_data(
        season=2020,
        team="Ohio State"
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for the 2020 Ohio State Buckeyes,
    # but exclude garbage time plays when making the PPA calculations.
    print(
        "Get team season PPA data for the 2020 Ohio State Buckeyes, " +
        "but exclude garbage time plays when making the PPA calculations."
    )
    json_data = get_cfbd_team_season_ppa_data(
        season=2020,
        team="Ohio State",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get team season PPA data for teams in
    # the Big 10 (B1G) Conference in the 2020 CFB Season.
    print(
        "Get team season PPA data for teams in " +
        "the Big 10 (B1G) Conference in the 2020 CFB Season."
    )
    json_data = get_cfbd_team_season_ppa_data(
        season=2020,
        conference="B1G"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_team_season_ppa_data(
        season=2020,
        conference="B1G",
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with team season PPA data, or (if return_as_dict is set to True) a dictionary object with a team season PPA data.

def get_cfbd_team_game_ppa_data( season: int, api_key: str = None, api_key_dir: str = None, week: int = None, team: str = None, conference: str = None, exclude_garbage_time: bool = False, season_type: str = 'regular', return_as_dict: bool = False):
 638def get_cfbd_team_game_ppa_data(
 639    season: int,
 640    api_key: str = None,
 641    api_key_dir: str = None,
 642    week: int = None,
 643    team: str = None,
 644    conference: str = None,
 645    exclude_garbage_time: bool = False,
 646    season_type: str = "regular",  # "regular" or "postseason"
 647    return_as_dict: bool = False,
 648):
 649    """
 650    Allows you to get team PPA data,
 651    at a game level,
 652    with or without garbage time plays,
 653    for a specified team and/or time period.
 654
 655    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
 656
 657    Parameters
 658    ----------
 659    `season` (int, mandatory):
 660        Required argument.
 661        Specifies the season you want team game PPA data information from.
 662        This must be specified, otherwise this package, and by extension
 663        the CFBD API, will not accept the request
 664        to get team game PPA data information.
 665
 666    `api_key` (str, optional):
 667        Semi-optional argument.
 668        If `api_key` is null, this function will attempt to load a CFBD API key
 669        from the python environment, or from a file on this computer.
 670        If `api_key` is not null,
 671        this function will automatically assume that the
 672        inputted `api_key` is a valid CFBD API key.
 673
 674    `api_key_dir` (str, optional):
 675        Optional argument.
 676        If `api_key` is set to am empty string, this variable is ignored.
 677        If `api_key_dir` is null, and `api_key` is null,
 678        this function will try to find
 679        a CFBD API key file in this user's home directory.
 680        If `api_key_dir` is set to a string, and `api_key` is null,
 681        this function will assume that `api_key_dir` is a directory,
 682        and will try to find a CFBD API key file in that directory.
 683
 684    `week` (int, optional):
 685        Optional argument.
 686        If `week` is set to an integer, this function will attempt
 687        to load team game PPA data from games in that season, and in that week.
 688
 689    `team` (str, optional):
 690        Optional argument.
 691        If you only want team game PPA data for a team,
 692        regardless if they are the home/away team,
 693        set `team` to the name of the team you want team game PPA data from.
 694
 695    `conference` (str, optional):
 696        Optional argument.
 697        If you only want team game PPA data from games
 698        involving teams a specific conference,
 699        set `conference` to the abbreviation
 700        of the conference you want team game PPA data from.
 701
 702    `exclude_garbage_time` (bool, optional):
 703        Optional argument.
 704        If you want to filter out plays where
 705        the result of the game is largely decided,
 706        set `exclude_garbage_time = True`.
 707        Default behavior is that this variable is set to
 708        `False` when this function is called.
 709
 710    `season_type` (str, semi-optional):
 711        Semi-optional argument.
 712        By default, this will be set to "regular", for the CFB regular season.
 713        If you want team game PPA data for non-regular season games,
 714        set `season_type` to "postseason".
 715        If `season_type` is set to anything but "regular" or "postseason",
 716        a `ValueError()` will be raised.
 717
 718    `return_as_dict` (bool, semi-optional):
 719        Semi-optional argument.
 720        If you want this function to return
 721        the data as a dictionary (read: JSON object),
 722        instead of a pandas `DataFrame` object,
 723        set `return_as_dict` to `True`.
 724
 725    Usage
 726    ----------
 727    ```
 728    import time
 729
 730    from cfbd_json_py.metrics import get_cfbd_team_game_ppa_data
 731
 732
 733    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
 734
 735    if cfbd_key != "tigersAreAwesome":
 736        print(
 737            "Using the user's API key declared in this script " +
 738            "for this example."
 739        )
 740
 741        # Get team PPA data for individual games within the 2020 CFB season.
 742        print(
 743            "Get team PPA data for individual games " +
 744            "within the 2020 CFB season."
 745        )
 746        json_data = get_cfbd_team_game_ppa_data(
 747            api_key=cfbd_key,
 748            season=2020
 749        )
 750        print(json_data)
 751        time.sleep(5)
 752
 753        # Get team PPA data for week 10 games within the 2020 CFB season.
 754        print(
 755            "Get team PPA data for week 10 games within the 2020 CFB season."
 756        )
 757        json_data = get_cfbd_team_game_ppa_data(
 758            api_key=cfbd_key,
 759            season=2020,
 760            week=10
 761        )
 762        print(json_data)
 763        time.sleep(5)
 764
 765        # Get team PPA data for
 766        # University of Cincinnati football games within the 2020 CFB season.
 767        print(
 768            "Get team PPA data for University of Cincinnati " +
 769            "football games within the 2020 CFB season."
 770        )
 771        json_data = get_cfbd_team_game_ppa_data(
 772            api_key=cfbd_key,
 773            season=2020,
 774            team="Cincinnati"
 775        )
 776        print(json_data)
 777        time.sleep(5)
 778
 779        # Get team PPA data for Southeastern Conference (SEC)
 780        # games within the 2020 CFB season.
 781        print(
 782            "Get team PPA data for Southeastern Conference (SEC) " +
 783            "games within the 2020 CFB season."
 784        )
 785        json_data = get_cfbd_team_game_ppa_data(
 786            api_key=cfbd_key,
 787            season=2020,
 788            conference="SEC"
 789        )
 790        print(json_data)
 791        time.sleep(5)
 792
 793        # Get team PPA data for Southeastern Conference (SEC)
 794        # games within the 2020 CFB season,
 795        # but exclude plays that occur in garbage time.
 796        print(
 797            "Get team PPA data for Southeastern Conference (SEC) games " +
 798            "within the 2020 CFB season, " +
 799            "but exclude plays that occur in garbage time."
 800        )
 801        json_data = get_cfbd_team_game_ppa_data(
 802            api_key=cfbd_key,
 803            season=2020,
 804            conference="SEC",
 805            exclude_garbage_time=True
 806        )
 807        print(json_data)
 808        time.sleep(5)
 809
 810        # Get team PPA data for postseason games in the 2020 CFB season.
 811        print("Get team PPA data for postseason games in the 2020 CFB season.")
 812        json_data = get_cfbd_team_game_ppa_data(
 813            api_key=cfbd_key,
 814            season=2020,
 815            season_type="postseason"
 816        )
 817        print(json_data)
 818        time.sleep(5)
 819
 820        # You can also tell this function to just return the API call as
 821        # a Dictionary (read: JSON) object.
 822        print(
 823            "You can also tell this function to just return the API call " +
 824            "as a Dictionary (read: JSON) object."
 825        )
 826        json_data = get_cfbd_team_game_ppa_data(
 827            api_key=cfbd_key,
 828            season=2020,
 829            team="Cincinnati",
 830            return_as_dict=True
 831        )
 832        print(json_data)
 833
 834    else:
 835        # Alternatively, if the CFBD API key exists in this python environment,
 836        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
 837        # you could just call these functions directly,
 838        # without setting the API key in the script.
 839        print(
 840            "Using the user's API key supposedly loaded into this " +
 841            "python environment for this example."
 842        )
 843
 844        # Get team PPA data for individual games within the 2020 CFB season.
 845        print(
 846            "Get team PPA data for individual games " +
 847            "within the 2020 CFB season."
 848        )
 849        json_data = get_cfbd_team_game_ppa_data(
 850            season=2020
 851        )
 852        print(json_data)
 853        time.sleep(5)
 854
 855        # Get team PPA data for week 10 games within the 2020 CFB season.
 856        print(
 857            "Get team PPA data for week 10 games within the 2020 CFB season."
 858        )
 859        json_data = get_cfbd_team_game_ppa_data(
 860            season=2020,
 861            week=10
 862        )
 863        print(json_data)
 864        time.sleep(5)
 865
 866        # Get team PPA data for
 867        # University of Cincinnati football games within the 2020 CFB season.
 868        print(
 869            "Get team PPA data for University of Cincinnati football " +
 870            "games within the 2020 CFB season."
 871        )
 872        json_data = get_cfbd_team_game_ppa_data(
 873            season=2020,
 874            team="Cincinnati"
 875        )
 876        print(json_data)
 877        time.sleep(5)
 878
 879        # Get team PPA data for Southeastern Conference (SEC)
 880        # games within the 2020 CFB season.
 881        print(
 882            "Get team PPA data for Southeastern Conference (SEC) games " +
 883            "within the 2020 CFB season."
 884        )
 885        json_data = get_cfbd_team_game_ppa_data(
 886            season=2020,
 887            conference="SEC"
 888        )
 889        print(json_data)
 890        time.sleep(5)
 891
 892        # Get team PPA data for Southeastern Conference (SEC)
 893        # games within the 2020 CFB season,
 894        # but exclude plays that occur in garbage time.
 895        print(
 896            "Get team PPA data for Southeastern Conference (SEC) games " +
 897            "within the 2020 CFB season, " +
 898            "but exclude plays that occur in garbage time."
 899        )
 900        json_data = get_cfbd_team_game_ppa_data(
 901            season=2020,
 902            conference="SEC",
 903            exclude_garbage_time=True
 904        )
 905        print(json_data)
 906        time.sleep(5)
 907
 908        # Get team PPA data for postseason games in the 2020 CFB season.
 909        print("Get team PPA data for postseason games in the 2020 CFB season.")
 910        json_data = get_cfbd_team_game_ppa_data(
 911            season=2020,
 912            season_type="postseason"
 913        )
 914        print(json_data)
 915        time.sleep(5)
 916
 917        # You can also tell this function to just return the API call as
 918        # a Dictionary (read: JSON) object.
 919        print(
 920            "You can also tell this function to just return the API call " +
 921            "as a Dictionary (read: JSON) object."
 922        )
 923        json_data = get_cfbd_team_game_ppa_data(
 924            season=2020,
 925            team="Cincinnati",
 926            return_as_dict=True
 927        )
 928        print(json_data)
 929
 930    ```
 931    Returns
 932    ----------
 933    A pandas `DataFrame` object with team PPA data,
 934    or (if `return_as_dict` is set to `True`)
 935    a dictionary object with team PPA data.
 936
 937    """
 938
 939    now = datetime.now()
 940    cfb_games_df = pd.DataFrame()
 941    # row_df = pd.DataFrame()
 942    url = "https://api.collegefootballdata.com/ppa/games"
 943
 944    ##########################################################################
 945
 946    if api_key is not None:
 947        real_api_key = api_key
 948        del api_key
 949    else:
 950        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
 951
 952    if real_api_key == "tigersAreAwesome":
 953        raise ValueError(
 954            "You actually need to change `cfbd_key` to your CFBD API key."
 955        )
 956    elif "Bearer " in real_api_key:
 957        pass
 958    elif "Bearer" in real_api_key:
 959        real_api_key = real_api_key.replace("Bearer", "Bearer ")
 960    else:
 961        real_api_key = "Bearer " + real_api_key
 962
 963    if season is None:
 964        # This should never happen without user tampering, but if it does,
 965        # we need to raise an error,
 966        # because the CFBD API will refuse this call without a valid season.
 967        raise SystemError(
 968            "I don't know how, I don't know why, "
 969            + "but you managed to call this function "
 970            + "while `season` was `None` (NULL),"
 971            + " and the function got to this point in the code."
 972            + "\nIf you have a GitHub account, "
 973            + "please raise an issue on this python package's GitHub page:\n"
 974            + "https://github.com/armstjc/cfbd-json-py/issues"
 975        )
 976    elif season > (now.year + 1):
 977        raise ValueError(f"`season` cannot be greater than {season}.")
 978    elif season < 1869:
 979        raise ValueError("`season` cannot be less than 1869.")
 980
 981    if season_type != "regular" and season_type != "postseason":
 982        raise ValueError(
 983            "`season_type` must be set to either "
 984            + '"regular" or "postseason" for this function to work.'
 985        )
 986
 987    if week is not None and week < 0:
 988        raise ValueError("`week` must be a positive number.")
 989
 990    if season_type != "regular" and season_type != "postseason":
 991        raise ValueError(
 992            "`season_type` must be set to either "
 993            + '"regular" or "postseason" for this function to work.'
 994        )
 995
 996    gt_str = ""
 997    if exclude_garbage_time is True:
 998        gt_str = "true"
 999    elif exclude_garbage_time is False:
1000        gt_str = "false"
1001
1002    # URL builder
1003    ##########################################################################
1004
1005    # Required by API
1006    url += f"?seasonType={season_type}"
1007    url += f"&year={season}"
1008
1009    if week is not None:
1010        url += f"&week={week}"
1011
1012    if team is not None:
1013        url += f"&team={team}"
1014
1015    if conference is not None:
1016        url += f"&conference={conference}"
1017
1018    if exclude_garbage_time is not None:
1019        url += f"&excludeGarbageTime={gt_str}"
1020
1021    headers = {
1022        "Authorization": f"{real_api_key}", "accept": "application/json"
1023    }
1024    response = requests.get(url, headers=headers)
1025
1026    if response.status_code == 200:
1027        pass
1028    elif response.status_code == 401:
1029        raise ConnectionRefusedError(
1030            "Could not connect. The connection was refused.\n" +
1031            "HTTP Status Code 401."
1032        )
1033    else:
1034        raise ConnectionError(
1035            f"Could not connect.\nHTTP Status code {response.status_code}"
1036        )
1037
1038    json_data = response.json()
1039
1040    if return_as_dict is True:
1041        return json_data
1042
1043    cfb_games_df = pd.json_normalize(json_data)
1044    cfb_games_df.rename(
1045        columns={
1046            "gameId": "game_id",
1047            "conference": "conference_name",
1048            "team": "team_name",
1049            "opponent": "opponent_name",
1050            "offense.overall": "ppa_offense_overall",
1051            "offense.passing": "ppa_offense_passing",
1052            "offense.rushing": "ppa_offense_rushing",
1053            "offense.firstDown": "ppa_offense_first_down",
1054            "offense.secondDown": "ppa_offense_second_down",
1055            "offense.thirdDown": "ppa_offense_third_down",
1056            "offense.cumulative.total": "ppa_offense_cumulative_total",
1057            "offense.cumulative.passing": "ppa_offense_cumulative_passing",
1058            "offense.cumulative.rushing": "ppa_offense_cumulative_rushing",
1059            "defense.overall": "ppa_defense_overall",
1060            "defense.passing": "ppa_defense_passing",
1061            "defense.rushing": "ppa_defense_rushing",
1062            "defense.firstDown": "ppa_defense_first_down",
1063            "defense.secondDown": "ppa_defense_second_down",
1064            "defense.thirdDown": "ppa_defense_third_down",
1065            "defense.cumulative.total": "ppa_defense_cumulative_total",
1066            "defense.cumulative.passing": "ppa_defense_cumulative_passing",
1067            "defense.cumulative.rushing": "ppa_defense_cumulative_rushing",
1068        },
1069        inplace=True,
1070    )
1071    return cfb_games_df

Allows you to get team PPA data, at a game level, with or without garbage time plays, for a specified team and/or time period.

PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).

Parameters

season (int, mandatory): Required argument. Specifies the season you want team game PPA data information from. This must be specified, otherwise this package, and by extension the CFBD API, will not accept the request to get team game PPA data information.

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

week (int, optional): Optional argument. If week is set to an integer, this function will attempt to load team game PPA data from games in that season, and in that week.

team (str, optional): Optional argument. If you only want team game PPA data for a team, regardless if they are the home/away team, set team to the name of the team you want team game PPA data from.

conference (str, optional): Optional argument. If you only want team game PPA data from games involving teams a specific conference, set conference to the abbreviation of the conference you want team game PPA data from.

exclude_garbage_time (bool, optional): Optional argument. If you want to filter out plays where the result of the game is largely decided, set exclude_garbage_time = True. Default behavior is that this variable is set to False when this function is called.

season_type (str, semi-optional): Semi-optional argument. By default, this will be set to "regular", for the CFB regular season. If you want team game PPA data for non-regular season games, set season_type to "postseason". If season_type is set to anything but "regular" or "postseason", a ValueError() will be raised.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_team_game_ppa_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get team PPA data for individual games within the 2020 CFB season.
    print(
        "Get team PPA data for individual games " +
        "within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for week 10 games within the 2020 CFB season.
    print(
        "Get team PPA data for week 10 games within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for
    # University of Cincinnati football games within the 2020 CFB season.
    print(
        "Get team PPA data for University of Cincinnati " +
        "football games within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Cincinnati"
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for Southeastern Conference (SEC)
    # games within the 2020 CFB season.
    print(
        "Get team PPA data for Southeastern Conference (SEC) " +
        "games within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        conference="SEC"
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for Southeastern Conference (SEC)
    # games within the 2020 CFB season,
    # but exclude plays that occur in garbage time.
    print(
        "Get team PPA data for Southeastern Conference (SEC) games " +
        "within the 2020 CFB season, " +
        "but exclude plays that occur in garbage time."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        conference="SEC",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for postseason games in the 2020 CFB season.
    print("Get team PPA data for postseason games in the 2020 CFB season.")
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_team_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Cincinnati",
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded into this " +
        "python environment for this example."
    )

    # Get team PPA data for individual games within the 2020 CFB season.
    print(
        "Get team PPA data for individual games " +
        "within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for week 10 games within the 2020 CFB season.
    print(
        "Get team PPA data for week 10 games within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        week=10
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for
    # University of Cincinnati football games within the 2020 CFB season.
    print(
        "Get team PPA data for University of Cincinnati football " +
        "games within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        team="Cincinnati"
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for Southeastern Conference (SEC)
    # games within the 2020 CFB season.
    print(
        "Get team PPA data for Southeastern Conference (SEC) games " +
        "within the 2020 CFB season."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        conference="SEC"
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for Southeastern Conference (SEC)
    # games within the 2020 CFB season,
    # but exclude plays that occur in garbage time.
    print(
        "Get team PPA data for Southeastern Conference (SEC) games " +
        "within the 2020 CFB season, " +
        "but exclude plays that occur in garbage time."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        conference="SEC",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get team PPA data for postseason games in the 2020 CFB season.
    print("Get team PPA data for postseason games in the 2020 CFB season.")
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_team_game_ppa_data(
        season=2020,
        team="Cincinnati",
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with team PPA data, or (if return_as_dict is set to True) a dictionary object with team PPA data.

def get_cfbd_player_game_ppa_data( api_key: str = None, api_key_dir: str = None, season: int = None, week: int = None, team: str = None, position: str = None, player_id: int = None, play_threshold: int = None, exclude_garbage_time: bool = False, season_type: str = 'regular', return_as_dict: bool = False):
1074def get_cfbd_player_game_ppa_data(
1075    api_key: str = None,
1076    api_key_dir: str = None,
1077    season: int = None,
1078    week: int = None,
1079    team: str = None,
1080    # A week or team must be specified
1081    position: str = None,
1082    player_id: int = None,
1083    play_threshold: int = None,
1084    exclude_garbage_time: bool = False,
1085    season_type: str = "regular",  # "regular" or "postseason"
1086    return_as_dict: bool = False,
1087):
1088    """
1089    Allows you to get player PPA data,
1090    at a game level,
1091    with or without garbage time plays,
1092    for a specified time period and/or team.
1093
1094    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
1095
1096    Parameters
1097    ----------
1098
1099    `api_key` (str, optional):
1100        Semi-optional argument.
1101        If `api_key` is null, this function will attempt to load a CFBD API key
1102        from the python environment, or from a file on this computer.
1103        If `api_key` is not null,
1104        this function will automatically assume that the
1105        inputted `api_key` is a valid CFBD API key.
1106
1107    `api_key_dir` (str, optional):
1108        Optional argument.
1109        If `api_key` is set to am empty string, this variable is ignored.
1110        If `api_key_dir` is null, and `api_key` is null,
1111        this function will try to find
1112        a CFBD API key file in this user's home directory.
1113        If `api_key_dir` is set to a string, and `api_key` is null,
1114        this function will assume that `api_key_dir` is a directory,
1115        and will try to find a CFBD API key file in that directory.
1116
1117    `season` (int, semi-optional):
1118        Semi-Optional argument.
1119        Specifies the season you want player game PPA data information from.
1120        This must be specified, otherwise this package, and by extension
1121        the CFBD API, will not accept the request
1122        to get player game PPA data information.
1123
1124    `week` (int, semi-optional):
1125        Semi-Optional argument.
1126        If `week` is set to an integer, this function will attempt
1127        to load player game PPA data from
1128        games in that season, and in that week.
1129        `week` and/or `team` must be set to a non-null value for this function
1130        to work.
1131
1132    `team` (str, semi-optional):
1133        Semi-Optional argument.
1134        If you only want player game PPA data for players of a specific team,
1135        regardless if they are the home/away team,
1136        set `team` to the name of the team you want player game PPA data from.
1137        `week` and/or `team` must be set to a non-null value for this function
1138        to work.
1139
1140    `position` (str, optional):
1141        Optional argument.
1142        If you only want player game PPA data
1143        for players of a specific position,
1144        set `position` to the position you want player game PPA data from.
1145
1146    `player_id` (int, optional):
1147        Optional argument.
1148        If you only want PPA data for a specific player ID,
1149        set this variable to the player ID
1150        of the player you want PPA data from.
1151
1152    `play_threshold`
1153        Optional argument.
1154        If you only want PPA data for players
1155        who touched the ball for *X* number of plays in a game,
1156        set `play_threshold = x`, where `x` is
1157        your specified minimum number of plays.
1158
1159    `exclude_garbage_time` (bool, optional):
1160        Optional argument.
1161        If you want to filter out plays where
1162        the result of the game is largely decided,
1163        set `exclude_garbage_time = True`.
1164        Default behavior is that this variable is set to
1165        `False` when this function is called.
1166
1167    `season_type` (str, semi-optional):
1168        Semi-optional argument.
1169        By default, this will be set to "regular", for the CFB regular season.
1170        If you want player game PPA data for non-regular season games,
1171        set `season_type` to "postseason".
1172        If `season_type` is set to anything but "regular" or "postseason",
1173        a `ValueError()` will be raised.
1174
1175    `return_as_dict` (bool, semi-optional):
1176        Semi-optional argument.
1177        If you want this function to return
1178        the data as a dictionary (read: JSON object),
1179        instead of a pandas `DataFrame` object,
1180        set `return_as_dict` to `True`.
1181
1182    Usage
1183    ----------
1184    ```
1185    import time
1186
1187    from cfbd_json_py.metrics import get_cfbd_player_game_ppa_data
1188
1189
1190    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
1191
1192    if cfbd_key != "tigersAreAwesome":
1193        print(
1194            "Using the user's API key declared in this script " +
1195            "for this example."
1196        )
1197
1198        # Get player game PPA data for week 10 of the 2020 CFB season.
1199        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1200        json_data = get_cfbd_player_game_ppa_data(
1201            api_key=cfbd_key,
1202            season=2020,
1203            week=10
1204        )
1205        print(json_data)
1206        time.sleep(5)
1207
1208        # Get player game PPA data for players of the
1209        # 2020 University of Cincinnati Football team.
1210        print(
1211            "Get player game PPA data for players of " +
1212            "the 2020 University of Cincinnati Football team."
1213        )
1214        json_data = get_cfbd_player_game_ppa_data(
1215            api_key=cfbd_key,
1216            season=2020,
1217            team="Cincinnati"
1218        )
1219        print(json_data)
1220        time.sleep(5)
1221
1222        # Get player game PPA data for QBs who played
1223        # in week 10 of the 2020 CFB season.
1224        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1225        json_data = get_cfbd_player_game_ppa_data(
1226            api_key=cfbd_key,
1227            season=2020,
1228            week=10,
1229            position="QB"
1230        )
1231        print(json_data)
1232        time.sleep(5)
1233
1234        # Get player game PPA data for QBs who
1235        # played in week 10 of the 2020 CFB season,
1236        # but exclude plays in garbage time.
1237        print(
1238            "Get player game PPA data for week 10 of the 2020 CFB season, " +
1239            "but exclude plays in garbage time."
1240        )
1241        json_data = get_cfbd_player_game_ppa_data(
1242            api_key=cfbd_key,
1243            season=2020,
1244            week=10,
1245            position="QB",
1246            exclude_garbage_time=True
1247        )
1248        print(json_data)
1249        time.sleep(5)
1250
1251        # Get player game PPA data for week 10 of the 2020 CFB season,
1252        # where a player touched the ball for at least 25 plays.
1253        print(
1254            "Get player game PPA data for week 10 of the 2020 " +
1255            "CFB season, where a player touched the ball " +
1256            "for at least 25 plays."
1257        )
1258        json_data = get_cfbd_player_game_ppa_data(
1259            api_key=cfbd_key,
1260            season=2020,
1261            week=10,
1262            play_threshold=25
1263        )
1264        print(json_data)
1265        time.sleep(5)
1266
1267        # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
1268        # during their postseason.
1269        print(
1270            "Get player game PPA data the 2020 Alabama Crimson Tide " +
1271            "Football team, during their postseason."
1272        )
1273        json_data = get_cfbd_player_game_ppa_data(
1274            api_key=cfbd_key,
1275            season=2020,
1276            team="Alabama",
1277            season_type="postseason"
1278        )
1279        print(json_data)
1280        time.sleep(5)
1281
1282        # You can also tell this function to just return the API call as
1283        # a Dictionary (read: JSON) object.
1284        print(
1285            "You can also tell this function to just return the API call " +
1286            "as a Dictionary (read: JSON) object."
1287        )
1288        json_data = get_cfbd_player_game_ppa_data(
1289            api_key=cfbd_key,
1290            season=2020,
1291            week=10,
1292            return_as_dict=True
1293        )
1294        print(json_data)
1295
1296    else:
1297        # Alternatively, if the CFBD API key exists in this python environment,
1298        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
1299        # you could just call these functions directly,
1300        # without setting the API key in the script.
1301        print(
1302            "Using the user's API key supposedly loaded into " +
1303            "this python environment for this example."
1304        )
1305
1306        # Get player game PPA data for week 10 of the 2020 CFB season.
1307        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1308        json_data = get_cfbd_player_game_ppa_data(
1309            season=2020,
1310            week=10
1311        )
1312        print(json_data)
1313        time.sleep(5)
1314
1315        # Get player game PPA data for players of the
1316        # 2020 University of Cincinnati Football team.
1317        print(
1318            "Get player game PPA data for players of " +
1319            "the 2020 University of Cincinnati Football team."
1320        )
1321        json_data = get_cfbd_player_game_ppa_data(
1322            season=2020,
1323            team="Cincinnati"
1324        )
1325        print(json_data)
1326        time.sleep(5)
1327
1328        # Get player game PPA data for QBs who played
1329        # in week 10 of the 2020 CFB season.
1330        print("Get player game PPA data for week 10 of the 2020 CFB season.")
1331        json_data = get_cfbd_player_game_ppa_data(
1332            season=2020,
1333            week=10,
1334            position="QB"
1335        )
1336        print(json_data)
1337        time.sleep(5)
1338
1339        # Get player game PPA data for QBs who played
1340        # in week 10 of the 2020 CFB season,
1341        # but exclude plays in garbage time.
1342        print(
1343            "Get player game PPA data for week 10 of the 2020 CFB season, " +
1344            "but exclude plays in garbage time."
1345        )
1346        json_data = get_cfbd_player_game_ppa_data(
1347            season=2020,
1348            week=10,
1349            position="QB",
1350            exclude_garbage_time=True
1351        )
1352        print(json_data)
1353        time.sleep(5)
1354
1355        # Get player game PPA data for week 10 of the 2020 CFB season,
1356        # where a player touched the ball for at least 25 plays.
1357        print(
1358            "Get player game PPA data for week 10 of the 2020 CFB season," +
1359            " where a player touched the ball for at least 25 plays."
1360        )
1361        json_data = get_cfbd_player_game_ppa_data(
1362            season=2020,
1363            week=10,
1364            play_threshold=25
1365        )
1366        print(json_data)
1367        time.sleep(5)
1368
1369        # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
1370        # during their postseason.
1371        print(
1372            "Get player game PPA data the 2020 Alabama Crimson Tide " +
1373            "Football team, during their postseason."
1374        )
1375        json_data = get_cfbd_player_game_ppa_data(
1376            season=2020,
1377            team="Alabama",
1378            season_type="postseason"
1379        )
1380        print(json_data)
1381        time.sleep(5)
1382
1383        # You can also tell this function to just return the API call as
1384        # a Dictionary (read: JSON) object.
1385        print(
1386            "You can also tell this function to just return the API call " +
1387            "as a Dictionary (read: JSON) object."
1388        )
1389        json_data = get_cfbd_player_game_ppa_data(
1390            season=2020,
1391            week=10,
1392            return_as_dict=True
1393        )
1394        print(json_data)
1395
1396    ```
1397    Returns
1398    ----------
1399    A pandas `DataFrame` object with player PPA data,
1400    or (if `return_as_dict` is set to `True`)
1401    a dictionary object with player PPA data.
1402
1403    """
1404
1405    now = datetime.now()
1406    cfb_games_df = pd.DataFrame()
1407    # row_df = pd.DataFrame()
1408    url = "https://api.collegefootballdata.com/ppa/players/games"
1409
1410    ##########################################################################
1411
1412    if api_key is not None:
1413        real_api_key = api_key
1414        del api_key
1415    else:
1416        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
1417
1418    if real_api_key == "tigersAreAwesome":
1419        raise ValueError(
1420            "You actually need to change `cfbd_key` to your CFBD API key."
1421        )
1422    elif "Bearer " in real_api_key:
1423        pass
1424    elif "Bearer" in real_api_key:
1425        real_api_key = real_api_key.replace("Bearer", "Bearer ")
1426    else:
1427        real_api_key = "Bearer " + real_api_key
1428
1429    if season is None:
1430        # This should never happen without user tampering, but if it does,
1431        # we need to raise an error,
1432        # because the CFBD API will refuse this call without a valid season.
1433        raise SystemError(
1434            "I don't know how, I don't know why, but you managed "
1435            + "to call this function while `season` was `None` (NULL),"
1436            + " and the function got to this point in the code."
1437            + "\nIf you have a GitHub account, "
1438            + "please raise an issue on this python package's GitHub page:\n"
1439            + "https://github.com/armstjc/cfbd-json-py/issues"
1440        )
1441    elif season > (now.year + 1):
1442        raise ValueError(f"`season` cannot be greater than {season}.")
1443    elif season < 1869:
1444        raise ValueError("`season` cannot be less than 1869.")
1445
1446    if week is None and team is None:
1447        raise ValueError(
1448            "To call this function, you must set `week` and/or `team` "
1449            + "to a non-null value."
1450        )
1451
1452    if season_type != "regular" and season_type != "postseason":
1453        raise ValueError(
1454            '`season_type` must be set to either ' +
1455            '"regular" or "postseason" for this function to work.'
1456        )
1457
1458    if week is not None and week < 0:
1459        raise ValueError("`week` must be a positive number.")
1460
1461    if season_type != "regular" and season_type != "postseason":
1462        raise ValueError(
1463            '`season_type` must be set to either ' +
1464            '"regular" or "postseason" for this function to work.'
1465        )
1466
1467    if play_threshold is not None and play_threshold < 0:
1468        raise ValueError(
1469            "`play_threshold` must be an integer at or greater than 0."
1470        )
1471
1472    gt_str = ""
1473    if exclude_garbage_time is True:
1474        gt_str = "true"
1475    elif exclude_garbage_time is False:
1476        gt_str = "false"
1477
1478    # URL builder
1479    ##########################################################################
1480
1481    url_elements = 0
1482
1483    if season is not None and url_elements == 0:
1484        url += f"?year={season}"
1485        url_elements += 1
1486    elif season is not None:
1487        url += f"&year={season}"
1488        url_elements += 1
1489
1490    if week is not None and url_elements == 0:
1491        url += f"?week={week}"
1492        url_elements += 1
1493    elif week is not None:
1494        url += f"&week={week}"
1495        url_elements += 1
1496
1497    if team is not None and url_elements == 0:
1498        url += f"?team={team}"
1499        url_elements += 1
1500    elif team is not None:
1501        url += f"&team={team}"
1502        url_elements += 1
1503
1504    if position is not None and url_elements == 0:
1505        url += f"?position={position}"
1506        url_elements += 1
1507    elif position is not None:
1508        url += f"&position={position}"
1509        url_elements += 1
1510
1511    if player_id is not None and url_elements == 0:
1512        url += f"?playerId={player_id}"
1513        url_elements += 1
1514    elif player_id is not None:
1515        url += f"&playerId={player_id}"
1516        url_elements += 1
1517
1518    if play_threshold is not None and url_elements == 0:
1519        url += f"?threshold={play_threshold}"
1520        url_elements += 1
1521    elif play_threshold is not None:
1522        url += f"&threshold={play_threshold}"
1523        url_elements += 1
1524
1525    if exclude_garbage_time is not None and url_elements == 0:
1526        url += f"?excludeGarbageTime={gt_str}"
1527        url_elements += 1
1528    elif exclude_garbage_time is not None:
1529        url += f"&excludeGarbageTime={gt_str}"
1530        url_elements += 1
1531
1532    if season_type is not None and url_elements == 0:
1533        url += f"?seasonType={season_type}"
1534        url_elements += 1
1535    elif season_type is not None:
1536        url += f"&seasonType={season_type}"
1537        url_elements += 1
1538
1539    headers = {
1540        "Authorization": f"{real_api_key}", "accept": "application/json"
1541    }
1542    response = requests.get(url, headers=headers)
1543
1544    if response.status_code == 200:
1545        pass
1546    elif response.status_code == 401:
1547        raise ConnectionRefusedError(
1548            "Could not connect. The connection was refused.\n" +
1549            "HTTP Status Code 401."
1550        )
1551    else:
1552        raise ConnectionError(
1553            f"Could not connect.\nHTTP Status code {response.status_code}"
1554        )
1555
1556    json_data = response.json()
1557
1558    if return_as_dict is True:
1559        return json_data
1560
1561    cfb_games_df = pd.json_normalize(json_data)
1562    cfb_games_df.rename(
1563        columns={
1564            "name": "player_name",
1565            "position": "position_abv",
1566            "team": "team_name",
1567            "opponent": "opponent_name",
1568            "averagePPA.all": "avg_ppa_cumulative",
1569            "averagePPA.pass": "avg_ppa_pass",
1570            "averagePPA.rush": "avg_ppa_rush",
1571        },
1572        inplace=True,
1573    )
1574
1575    return cfb_games_df

Allows you to get player PPA data, at a game level, with or without garbage time plays, for a specified time period and/or team.

PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).

Parameters

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

season (int, semi-optional): Semi-Optional argument. Specifies the season you want player game PPA data information from. This must be specified, otherwise this package, and by extension the CFBD API, will not accept the request to get player game PPA data information.

week (int, semi-optional): Semi-Optional argument. If week is set to an integer, this function will attempt to load player game PPA data from games in that season, and in that week. week and/or team must be set to a non-null value for this function to work.

team (str, semi-optional): Semi-Optional argument. If you only want player game PPA data for players of a specific team, regardless if they are the home/away team, set team to the name of the team you want player game PPA data from. week and/or team must be set to a non-null value for this function to work.

position (str, optional): Optional argument. If you only want player game PPA data for players of a specific position, set position to the position you want player game PPA data from.

player_id (int, optional): Optional argument. If you only want PPA data for a specific player ID, set this variable to the player ID of the player you want PPA data from.

play_threshold Optional argument. If you only want PPA data for players who touched the ball for X number of plays in a game, set play_threshold = x, where x is your specified minimum number of plays.

exclude_garbage_time (bool, optional): Optional argument. If you want to filter out plays where the result of the game is largely decided, set exclude_garbage_time = True. Default behavior is that this variable is set to False when this function is called.

season_type (str, semi-optional): Semi-optional argument. By default, this will be set to "regular", for the CFB regular season. If you want player game PPA data for non-regular season games, set season_type to "postseason". If season_type is set to anything but "regular" or "postseason", a ValueError() will be raised.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_player_game_ppa_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get player game PPA data for week 10 of the 2020 CFB season.
    print("Get player game PPA data for week 10 of the 2020 CFB season.")
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for players of the
    # 2020 University of Cincinnati Football team.
    print(
        "Get player game PPA data for players of " +
        "the 2020 University of Cincinnati Football team."
    )
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Cincinnati"
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for QBs who played
    # in week 10 of the 2020 CFB season.
    print("Get player game PPA data for week 10 of the 2020 CFB season.")
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10,
        position="QB"
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for QBs who
    # played in week 10 of the 2020 CFB season,
    # but exclude plays in garbage time.
    print(
        "Get player game PPA data for week 10 of the 2020 CFB season, " +
        "but exclude plays in garbage time."
    )
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10,
        position="QB",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for week 10 of the 2020 CFB season,
    # where a player touched the ball for at least 25 plays.
    print(
        "Get player game PPA data for week 10 of the 2020 " +
        "CFB season, where a player touched the ball " +
        "for at least 25 plays."
    )
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10,
        play_threshold=25
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
    # during their postseason.
    print(
        "Get player game PPA data the 2020 Alabama Crimson Tide " +
        "Football team, during their postseason."
    )
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Alabama",
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_player_game_ppa_data(
        api_key=cfbd_key,
        season=2020,
        week=10,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded into " +
        "this python environment for this example."
    )

    # Get player game PPA data for week 10 of the 2020 CFB season.
    print("Get player game PPA data for week 10 of the 2020 CFB season.")
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        week=10
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for players of the
    # 2020 University of Cincinnati Football team.
    print(
        "Get player game PPA data for players of " +
        "the 2020 University of Cincinnati Football team."
    )
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        team="Cincinnati"
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for QBs who played
    # in week 10 of the 2020 CFB season.
    print("Get player game PPA data for week 10 of the 2020 CFB season.")
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        week=10,
        position="QB"
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for QBs who played
    # in week 10 of the 2020 CFB season,
    # but exclude plays in garbage time.
    print(
        "Get player game PPA data for week 10 of the 2020 CFB season, " +
        "but exclude plays in garbage time."
    )
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        week=10,
        position="QB",
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data for week 10 of the 2020 CFB season,
    # where a player touched the ball for at least 25 plays.
    print(
        "Get player game PPA data for week 10 of the 2020 CFB season," +
        " where a player touched the ball for at least 25 plays."
    )
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        week=10,
        play_threshold=25
    )
    print(json_data)
    time.sleep(5)

    # Get player game PPA data the 2020 Alabama Crimson Tide Football team,
    # during their postseason.
    print(
        "Get player game PPA data the 2020 Alabama Crimson Tide " +
        "Football team, during their postseason."
    )
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        team="Alabama",
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_player_game_ppa_data(
        season=2020,
        week=10,
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with player PPA data, or (if return_as_dict is set to True) a dictionary object with player PPA data.

def get_cfbd_player_season_ppa_data( api_key: str = None, api_key_dir: str = None, season: int = None, team: str = None, conference: str = None, position: str = None, player_id: int = None, play_threshold: int = None, exclude_garbage_time: bool = False, return_as_dict: bool = False):
1578def get_cfbd_player_season_ppa_data(
1579    api_key: str = None,
1580    api_key_dir: str = None,
1581    season: int = None,
1582    team: str = None,
1583    conference: str = None,
1584    position: str = None,
1585    player_id: int = None,
1586    play_threshold: int = None,
1587    exclude_garbage_time: bool = False,
1588    return_as_dict: bool = False,
1589):
1590    """
1591    Allows you to get player PPA data,
1592    at a season level,
1593    with or without garbage time plays,
1594    for a specified time period and/or team.
1595
1596    PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).
1597
1598    Parameters
1599    ----------
1600
1601    `api_key` (str, optional):
1602        Semi-optional argument.
1603        If `api_key` is null, this function will attempt to load a CFBD API key
1604        from the python environment, or from a file on this computer.
1605        If `api_key` is not null,
1606        this function will automatically assume that the
1607        inputted `api_key` is a valid CFBD API key.
1608
1609    `api_key_dir` (str, optional):
1610        Optional argument.
1611        If `api_key` is set to am empty string, this variable is ignored.
1612        If `api_key_dir` is null, and `api_key` is null,
1613        this function will try to find
1614        a CFBD API key file in this user's home directory.
1615        If `api_key_dir` is set to a string, and `api_key` is null,
1616        this function will assume that `api_key_dir` is a directory,
1617        and will try to find a CFBD API key file in that directory.
1618
1619    `season` (int, semi-optional):
1620        Semi-Optional argument.
1621        Specifies the season you want player season PPA data information from.
1622        This must be specified, otherwise this package, and by extension
1623        the CFBD API, will not accept the request
1624        to get player season PPA data information.
1625
1626
1627    `team` (str, semi-optional):
1628        Semi-Optional argument.
1629        If you only want player season PPA data for players of a specific team,
1630        regardless if they are the home/away team,
1631        set `team` to the name of the team
1632        you want player season PPA data from.
1633        `week` and/or `team` must be set to a non-null value for this function
1634        to work.
1635
1636    `conference` (str, optional):
1637        Optional argument.
1638        If you only want player season PPA data from games
1639        involving teams from a specific conference,
1640        set `conference` to the abbreviation
1641        of the conference you want player season PPA data from.
1642        For a list of conferences,
1643        use the `cfbd_json_py.conferences.get_cfbd_conference_info()`
1644        function.
1645
1646    `position` (str, optional):
1647        Optional argument.
1648        If you only want player season PPA data
1649        for players of a specific position,
1650        set `position` to the position you want player season PPA data from.
1651
1652    `player_id` (int, optional):
1653        Optional argument.
1654        If you only want PPA data for a specific player ID,
1655        set this variable to the player ID
1656        of the player you want PPA data from.
1657
1658    `play_threshold`
1659        Optional argument.
1660        If you only want PPA data for players
1661        who touched the ball for *X* number of plays in a game,
1662        set `play_threshold = x`, where `x` is
1663        your specified minimum number of plays.
1664
1665    `exclude_garbage_time` (bool, optional):
1666        Optional argument.
1667        If you want to filter out plays where
1668        the result of the game is largely decided,
1669        set `exclude_garbage_time = True`.
1670        Default behavior is that this variable is set to
1671        `False` when this function is called.
1672
1673
1674    `return_as_dict` (bool, semi-optional):
1675        Semi-optional argument.
1676        If you want this function to return the data
1677        as a dictionary (read: JSON object),
1678        instead of a pandas `DataFrame` object,
1679        set `return_as_dict` to `True`.
1680
1681    Usage
1682    ----------
1683    ```
1684    import time
1685
1686    from cfbd_json_py.metrics import get_cfbd_player_season_ppa_data
1687
1688
1689    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
1690
1691    if cfbd_key != "tigersAreAwesome":
1692        print(
1693            "Using the user's API key declared in this script " +
1694            "for this example."
1695        )
1696
1697        # Get player season PPA data for the 2020 CFB season.
1698        print("Get player season PPA data for the 2020 CFB season.")
1699        json_data = get_cfbd_player_season_ppa_data(
1700            api_key=cfbd_key,
1701            season=2020
1702        )
1703        print(json_data)
1704        time.sleep(5)
1705
1706        # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
1707        print(
1708            "Get player season PPA data for " +
1709            "the 2020 Ohio Bobcats Football Team."
1710        )
1711        json_data = get_cfbd_player_season_ppa_data(
1712            api_key=cfbd_key,
1713            season=2020,
1714            team="Ohio"
1715        )
1716        print(json_data)
1717        time.sleep(5)
1718
1719        # Get player season PPA data for players who played on
1720        # teams within the Southeastern Conference (SEC) for the
1721        # 2020 CFB Season.
1722        print(
1723            "Get player season PPA data for players who played on teams " +
1724            "within the Southeastern Conference (SEC) for the 2020 CFB Season."
1725        )
1726        json_data = get_cfbd_player_season_ppa_data(
1727            api_key=cfbd_key,
1728            season=2020,
1729            conference="SEC"
1730        )
1731        print(json_data)
1732        time.sleep(5)
1733
1734        # Get player season PPA data from QBs in the 2020 CFB Season.
1735        print("Get player season PPA data from QBs in the 2020 CFB Season.")
1736        json_data = get_cfbd_player_season_ppa_data(
1737            api_key=cfbd_key,
1738            season=2020,
1739            position="QB"
1740        )
1741        print(json_data)
1742        time.sleep(5)
1743
1744        # Get player season PPA data from
1745        # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
1746        print(
1747            "Get player season PPA data from former " +
1748            "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
1749        )
1750        json_data = get_cfbd_player_season_ppa_data(
1751            api_key=cfbd_key,
1752            player_id=3915511
1753        )
1754        print(json_data)
1755        time.sleep(5)
1756
1757        # Get player season PPA data from
1758        # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
1759        # but exclude plays that occurred in garbage time.
1760        print(
1761            "Get player season PPA data from former " +
1762            "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
1763            "but exclude plays that occurred in garbage time."
1764        )
1765        json_data = get_cfbd_player_season_ppa_data(
1766            api_key=cfbd_key,
1767            player_id=3915511,
1768            exclude_garbage_time=True
1769        )
1770        print(json_data)
1771        time.sleep(5)
1772
1773        # Get player season PPA data from the 2020 CFB Season,
1774        # for players with at least 100 plays/touches.
1775        print(
1776            "Get player season PPA data from the 2020 CFB Season, " +
1777            "for players with at least 100 plays/touches."
1778        )
1779        json_data = get_cfbd_player_season_ppa_data(
1780            api_key=cfbd_key,
1781            season=2020,
1782            play_threshold=100
1783        )
1784        print(json_data)
1785        time.sleep(5)
1786
1787        # You can also tell this function to just return the API call as
1788        # a Dictionary (read: JSON) object.
1789        print(
1790            "You can also tell this function to just return the API call " +
1791            "as a Dictionary (read: JSON) object."
1792        )
1793        json_data = get_cfbd_player_season_ppa_data(
1794            api_key=cfbd_key,
1795            season=2020,
1796            return_as_dict=True
1797        )
1798        print(json_data)
1799
1800    else:
1801        # Alternatively, if the CFBD API key exists in this python environment,
1802        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
1803        # you could just call these functions directly,
1804        # without setting the API key in the script.
1805        print(
1806            "Using the user's API key supposedly loaded into " +
1807            "this python environment for this example."
1808        )
1809
1810        # Get player season PPA data for the 2020 CFB season.
1811        print("Get player season PPA data for the 2020 CFB season.")
1812        json_data = get_cfbd_player_season_ppa_data(
1813            season=2020
1814        )
1815        print(json_data)
1816        time.sleep(5)
1817
1818        # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
1819        print(
1820            "Get player season PPA data for " +
1821            "the 2020 Ohio Bobcats Football Team."
1822        )
1823        json_data = get_cfbd_player_season_ppa_data(
1824            season=2020,
1825            team="Ohio"
1826        )
1827        print(json_data)
1828        time.sleep(5)
1829
1830        # Get player season PPA data for players who played on
1831        # teams within the Southeastern Conference (SEC) for the
1832        # 2020 CFB Season.
1833        print(
1834            "Get player season PPA data for players who played on teams " +
1835            "within the Southeastern Conference (SEC) for the 2020 CFB Season."
1836        )
1837        json_data = get_cfbd_player_season_ppa_data(
1838            season=2020,
1839            conference="SEC"
1840        )
1841        print(json_data)
1842        time.sleep(5)
1843
1844        # Get player season PPA data from QBs in the 2020 CFB Season.
1845        print("Get player season PPA data from QBs in the 2020 CFB Season.")
1846        json_data = get_cfbd_player_season_ppa_data(
1847            season=2020,
1848            position="QB"
1849        )
1850        print(json_data)
1851        time.sleep(5)
1852
1853        # Get player season PPA data from
1854        # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
1855        print(
1856            "Get player season PPA data from former " +
1857            "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
1858        )
1859        json_data = get_cfbd_player_season_ppa_data(
1860            player_id=3915511
1861        )
1862        print(json_data)
1863        time.sleep(5)
1864
1865        # Get player season PPA data from
1866        # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
1867        # but exclude plays that occurred in garbage time.
1868        print(
1869            "Get player season PPA data from former " +
1870            "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
1871            "but exclude plays that occurred in garbage time."
1872        )
1873        json_data = get_cfbd_player_season_ppa_data(
1874            player_id=3915511,
1875            exclude_garbage_time=True
1876        )
1877        print(json_data)
1878        time.sleep(5)
1879
1880        # Get player season PPA data from the 2020 CFB Season,
1881        # for players with at least 100 plays/touches.
1882        print(
1883            "Get player season PPA data from the 2020 CFB Season, " +
1884            "for players with at least 100 plays/touches."
1885        )
1886        json_data = get_cfbd_player_season_ppa_data(
1887            season=2020,
1888            play_threshold=100
1889        )
1890        print(json_data)
1891        time.sleep(5)
1892
1893        # You can also tell this function to just return the API call as
1894        # a Dictionary (read: JSON) object.
1895        print(
1896            "You can also tell this function to just return the API call " +
1897            "as a Dictionary (read: JSON) object."
1898        )
1899        json_data = get_cfbd_player_season_ppa_data(
1900            season=2020,
1901            return_as_dict=True
1902        )
1903        print(json_data)
1904
1905    ```
1906    Returns
1907    ----------
1908    A pandas `DataFrame` object with player PPA data,
1909    or (if `return_as_dict` is set to `True`)
1910    a dictionary object with player PPA data.
1911
1912    """
1913    now = datetime.now()
1914    cfb_games_df = pd.DataFrame()
1915    # row_df = pd.DataFrame()
1916    url = "https://api.collegefootballdata.com/ppa/players/season"
1917
1918    ##########################################################################
1919
1920    if api_key is not None:
1921        real_api_key = api_key
1922        del api_key
1923    else:
1924        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
1925
1926    if real_api_key == "tigersAreAwesome":
1927        raise ValueError(
1928            "You actually need to change `cfbd_key` to your CFBD API key."
1929        )
1930    elif "Bearer " in real_api_key:
1931        pass
1932    elif "Bearer" in real_api_key:
1933        real_api_key = real_api_key.replace("Bearer", "Bearer ")
1934    else:
1935        real_api_key = "Bearer " + real_api_key
1936
1937    if season is None:
1938        pass
1939    elif season > (now.year + 1):
1940        raise ValueError(f"`season` cannot be greater than {season}.")
1941    elif season < 1869:
1942        raise ValueError("`season` cannot be less than 1869.")
1943
1944    if play_threshold is not None and play_threshold < 0:
1945        raise ValueError(
1946            "`play_threshold` must be an integer at or greater than 0."
1947        )
1948
1949    gt_str = ""
1950    if exclude_garbage_time is True:
1951        gt_str = "true"
1952    elif exclude_garbage_time is False:
1953        gt_str = "false"
1954
1955    # URL builder
1956    ##########################################################################
1957
1958    url_elements = 0
1959
1960    if season is not None and url_elements == 0:
1961        url += f"?year={season}"
1962        url_elements += 1
1963    elif season is not None:
1964        url += f"&year={season}"
1965        url_elements += 1
1966
1967    if team is not None and url_elements == 0:
1968        url += f"?team={team}"
1969        url_elements += 1
1970    elif team is not None:
1971        url += f"&team={team}"
1972        url_elements += 1
1973
1974    if conference is not None and url_elements == 0:
1975        url += f"?conference={conference}"
1976        url_elements += 1
1977    elif conference is not None:
1978        url += f"&conference={conference}"
1979        url_elements += 1
1980
1981    if position is not None and url_elements == 0:
1982        url += f"?position={position}"
1983        url_elements += 1
1984    elif position is not None:
1985        url += f"&position={position}"
1986        url_elements += 1
1987
1988    if player_id is not None and url_elements == 0:
1989        url += f"?playerId={player_id}"
1990        url_elements += 1
1991    elif player_id is not None:
1992        url += f"&playerId={player_id}"
1993        url_elements += 1
1994
1995    if play_threshold is not None and url_elements == 0:
1996        url += f"?threshold={play_threshold}"
1997        url_elements += 1
1998    elif play_threshold is not None:
1999        url += f"&threshold={play_threshold}"
2000        url_elements += 1
2001
2002    if exclude_garbage_time is not None and url_elements == 0:
2003        url += f"?excludeGarbageTime={gt_str}"
2004        url_elements += 1
2005    elif exclude_garbage_time is not None:
2006        url += f"&excludeGarbageTime={gt_str}"
2007        url_elements += 1
2008
2009    headers = {
2010        "Authorization": f"{real_api_key}", "accept": "application/json"
2011    }
2012    response = requests.get(url, headers=headers)
2013
2014    if response.status_code == 200:
2015        pass
2016    elif response.status_code == 401:
2017        raise ConnectionRefusedError(
2018            "Could not connect. The connection was refused.\n" +
2019            "HTTP Status Code 401."
2020        )
2021    else:
2022        raise ConnectionError(
2023            f"Could not connect.\nHTTP Status code {response.status_code}"
2024        )
2025
2026    json_data = response.json()
2027
2028    if return_as_dict is True:
2029        return json_data
2030
2031    cfb_games_df = pd.json_normalize(json_data)
2032    cfb_games_df.rename(
2033        columns={
2034            "id": "game_id",
2035            "name": "player_name",
2036            "position": "position_abv",
2037            "team": "team_name",
2038            "conference": "conference_name",
2039            "countablePlays": "countable_plays",
2040            "averagePPA.all": "avg_ppa_all",
2041            "averagePPA.pass": "avg_ppa_pass",
2042            "averagePPA.rush": "avg_ppa_rush",
2043            "averagePPA.firstDown": "avg_ppa_first_down",
2044            "averagePPA.secondDown": "avg_ppa_second_down",
2045            "averagePPA.thirdDown": "avg_ppa_third_down",
2046            "averagePPA.standardDowns": "avg_ppa_standard_downs",
2047            "averagePPA.passingDowns": "avg_ppa_passing_downs",
2048            "totalPPA.all": "total_ppa_all",
2049            "totalPPA.pass": "total_ppa_pass",
2050            "totalPPA.rush": "total_ppa_rush",
2051            "totalPPA.firstDown": "total_ppa_first_down",
2052            "totalPPA.secondDown": "total_ppa_second_down",
2053            "totalPPA.thirdDown": "total_ppa_third_down",
2054            "totalPPA.standardDowns": "total_ppa_standard_downs",
2055            "totalPPA.passingDowns": "total_ppa_passing_downs",
2056        },
2057        inplace=True,
2058    )
2059    return cfb_games_df

Allows you to get player PPA data, at a season level, with or without garbage time plays, for a specified time period and/or team.

PPA is the CFBD API's equivalent metric to Expected Points Added (EPA).

Parameters

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

season (int, semi-optional): Semi-Optional argument. Specifies the season you want player season PPA data information from. This must be specified, otherwise this package, and by extension the CFBD API, will not accept the request to get player season PPA data information.

team (str, semi-optional): Semi-Optional argument. If you only want player season PPA data for players of a specific team, regardless if they are the home/away team, set team to the name of the team you want player season PPA data from. week and/or team must be set to a non-null value for this function to work.

conference (str, optional): Optional argument. If you only want player season PPA data from games involving teams from a specific conference, set conference to the abbreviation of the conference you want player season PPA data from. For a list of conferences, use the cfbd_json_py.conferences.get_cfbd_conference_info() function.

position (str, optional): Optional argument. If you only want player season PPA data for players of a specific position, set position to the position you want player season PPA data from.

player_id (int, optional): Optional argument. If you only want PPA data for a specific player ID, set this variable to the player ID of the player you want PPA data from.

play_threshold Optional argument. If you only want PPA data for players who touched the ball for X number of plays in a game, set play_threshold = x, where x is your specified minimum number of plays.

exclude_garbage_time (bool, optional): Optional argument. If you want to filter out plays where the result of the game is largely decided, set exclude_garbage_time = True. Default behavior is that this variable is set to False when this function is called.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_player_season_ppa_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get player season PPA data for the 2020 CFB season.
    print("Get player season PPA data for the 2020 CFB season.")
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
    print(
        "Get player season PPA data for " +
        "the 2020 Ohio Bobcats Football Team."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        team="Ohio"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data for players who played on
    # teams within the Southeastern Conference (SEC) for the
    # 2020 CFB Season.
    print(
        "Get player season PPA data for players who played on teams " +
        "within the Southeastern Conference (SEC) for the 2020 CFB Season."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        conference="SEC"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from QBs in the 2020 CFB Season.
    print("Get player season PPA data from QBs in the 2020 CFB Season.")
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        position="QB"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from
    # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
    print(
        "Get player season PPA data from former " +
        "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        player_id=3915511
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from
    # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
    # but exclude plays that occurred in garbage time.
    print(
        "Get player season PPA data from former " +
        "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
        "but exclude plays that occurred in garbage time."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        player_id=3915511,
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from the 2020 CFB Season,
    # for players with at least 100 plays/touches.
    print(
        "Get player season PPA data from the 2020 CFB Season, " +
        "for players with at least 100 plays/touches."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        play_threshold=100
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_player_season_ppa_data(
        api_key=cfbd_key,
        season=2020,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded into " +
        "this python environment for this example."
    )

    # Get player season PPA data for the 2020 CFB season.
    print("Get player season PPA data for the 2020 CFB season.")
    json_data = get_cfbd_player_season_ppa_data(
        season=2020
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from the 2020 Ohio Bobcats Football Team.
    print(
        "Get player season PPA data for " +
        "the 2020 Ohio Bobcats Football Team."
    )
    json_data = get_cfbd_player_season_ppa_data(
        season=2020,
        team="Ohio"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data for players who played on
    # teams within the Southeastern Conference (SEC) for the
    # 2020 CFB Season.
    print(
        "Get player season PPA data for players who played on teams " +
        "within the Southeastern Conference (SEC) for the 2020 CFB Season."
    )
    json_data = get_cfbd_player_season_ppa_data(
        season=2020,
        conference="SEC"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from QBs in the 2020 CFB Season.
    print("Get player season PPA data from QBs in the 2020 CFB Season.")
    json_data = get_cfbd_player_season_ppa_data(
        season=2020,
        position="QB"
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from
    # former Ohio State and LSU QB Joe Burrow (player ID #3915511).
    print(
        "Get player season PPA data from former " +
        "Ohio State and LSU QB Joe Burrow (player ID #3915511)."
    )
    json_data = get_cfbd_player_season_ppa_data(
        player_id=3915511
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from
    # former Ohio State and LSU QB Joe Burrow (player ID #3915511),
    # but exclude plays that occurred in garbage time.
    print(
        "Get player season PPA data from former " +
        "Ohio State and LSU QB Joe Burrow (player ID #3915511), " +
        "but exclude plays that occurred in garbage time."
    )
    json_data = get_cfbd_player_season_ppa_data(
        player_id=3915511,
        exclude_garbage_time=True
    )
    print(json_data)
    time.sleep(5)

    # Get player season PPA data from the 2020 CFB Season,
    # for players with at least 100 plays/touches.
    print(
        "Get player season PPA data from the 2020 CFB Season, " +
        "for players with at least 100 plays/touches."
    )
    json_data = get_cfbd_player_season_ppa_data(
        season=2020,
        play_threshold=100
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_player_season_ppa_data(
        season=2020,
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with player PPA data, or (if return_as_dict is set to True) a dictionary object with player PPA data.

def get_cfbd_game_win_probability_data( game_id: int, api_key: str = None, api_key_dir: str = None, return_as_dict: bool = False):
2062def get_cfbd_game_win_probability_data(
2063    game_id: int,
2064    api_key: str = None,
2065    api_key_dir: str = None,
2066    return_as_dict: bool = False,
2067):
2068    """
2069    Allows one to get win probability data for a given game ID.
2070
2071    Parameters
2072    ----------
2073
2074    `game_id` (int, mandatory):
2075        Mandatory argument.
2076        This is the game ID for the game you want win probability data from,
2077        at the play-by-play level.
2078
2079    `api_key` (str, optional):
2080        Semi-optional argument.
2081        If `api_key` is null, this function will attempt to load a CFBD API key
2082        from the python environment, or from a file on this computer.
2083        If `api_key` is not null,
2084        this function will automatically assume that the
2085        inputted `api_key` is a valid CFBD API key.
2086
2087    `api_key_dir` (str, optional):
2088        Optional argument.
2089        If `api_key` is set to am empty string, this variable is ignored.
2090        If `api_key_dir` is null, and `api_key` is null,
2091        this function will try to find
2092        a CFBD API key file in this user's home directory.
2093        If `api_key_dir` is set to a string, and `api_key` is null,
2094        this function will assume that `api_key_dir` is a directory,
2095        and will try to find a CFBD API key file in that directory.
2096
2097    `return_as_dict` (bool, semi-optional):
2098        Semi-optional argument.
2099        If you want this function to return
2100        the data as a dictionary (read: JSON object),
2101        instead of a pandas `DataFrame` object,
2102        set `return_as_dict` to `True`.
2103
2104    Usage
2105    ----------
2106    ```
2107    import time
2108
2109    from cfbd_json_py.metrics import get_cfbd_game_win_probability_data
2110
2111
2112    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2113
2114    if cfbd_key != "tigersAreAwesome":
2115        print(
2116            "Using the user's API key declared in this script " +
2117            "for this example."
2118        )
2119
2120        # Get the win probability data for a 2017 game between
2121        # the University of Cincinnati and UConn (game ID #400941851).
2122        print(
2123            "Get the win probability data for a 2017 game between " +
2124            "the University of Cincinnati and UConn (game ID #400941851)."
2125        )
2126        json_data = get_cfbd_game_win_probability_data(
2127            api_key=cfbd_key,
2128            game_id=400941851
2129        )
2130        print(json_data)
2131        time.sleep(5)
2132
2133        # Get the win probability data for a 2023 game between
2134        # the University of Duke and
2135        # the University of Louisville (game ID #401525535).
2136        print(
2137            "Get the win probability data for a 2023 game between " +
2138            "the University of Duke and " +
2139            "the University of Louisville (game ID #401525535)."
2140        )
2141        json_data = get_cfbd_game_win_probability_data(
2142            api_key=cfbd_key,
2143            game_id=401525535
2144        )
2145        print(json_data)
2146        time.sleep(5)
2147
2148
2149        # You can also tell this function to just return the API call as
2150        # a Dictionary (read: JSON) object.
2151        print(
2152            "You can also tell this function to just return the API call " +
2153            "as a Dictionary (read: JSON) object."
2154        )
2155        json_data = get_cfbd_game_win_probability_data(
2156            api_key=cfbd_key,
2157            game_id=400941851,
2158            return_as_dict=True
2159        )
2160        print(json_data)
2161
2162    else:
2163        # Alternatively, if the CFBD API key exists in this python environment,
2164        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2165        # you could just call these functions directly,
2166        # without setting the API key in the script.
2167        print(
2168            "Using the user's API key supposedly loaded into " +
2169            "this python environment for this example."
2170        )
2171
2172        # Get win probability data for a 2017 game between
2173        # the University of Cincinnati and UConn (game ID #400941851).
2174        print(
2175            "Get the win probability data for a 2017 game between " +
2176            "the University of Cincinnati and UConn (game ID #400941851)."
2177        )
2178        json_data = get_cfbd_game_win_probability_data(
2179            game_id=400941851
2180        )
2181        print(json_data)
2182        time.sleep(5)
2183
2184        # Get win probability data for a 2023 game between
2185        # the University of Duke and
2186        # the University of Louisville (game ID #401525535).
2187        print(
2188            "Get the win probability data for a 2023 game between " +
2189            "the University of Duke and " +
2190            "the University of Louisville (game ID #401525535)."
2191        )
2192        json_data = get_cfbd_game_win_probability_data(
2193            game_id=401525535
2194        )
2195        print(json_data)
2196        time.sleep(5)
2197
2198
2199        # You can also tell this function to just return the API call as
2200        # a Dictionary (read: JSON) object.
2201        print(
2202            "You can also tell this function to just return " +
2203            "the API call as a Dictionary (read: JSON) object."
2204        )
2205        json_data = get_cfbd_game_win_probability_data(
2206            game_id=400941851,
2207            return_as_dict=True
2208        )
2209        print(json_data)
2210
2211    ```
2212    Returns
2213    ----------
2214    A pandas `DataFrame` object with win probability data
2215    at the play-by-play level,
2216    or (if `return_as_dict` is set to `True`)
2217    a dictionary object with win probability data at the play-by-play level.
2218
2219    """
2220
2221    wp_df = pd.DataFrame()
2222    # row_df = pd.DataFrame()
2223    url = "https://api.collegefootballdata.com/metrics/wp"
2224
2225    ##########################################################################
2226
2227    if api_key is not None:
2228        real_api_key = api_key
2229        del api_key
2230    else:
2231        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2232
2233    if real_api_key == "tigersAreAwesome":
2234        raise ValueError(
2235            "You actually need to change `cfbd_key` to your CFBD API key."
2236        )
2237    elif "Bearer " in real_api_key:
2238        pass
2239    elif "Bearer" in real_api_key:
2240        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2241    else:
2242        real_api_key = "Bearer " + real_api_key
2243    # URL builder
2244    ##########################################################################
2245
2246    # Required by API
2247    url += f"?gameId={game_id}"
2248
2249    headers = {
2250        "Authorization": f"{real_api_key}", "accept": "application/json"
2251    }
2252
2253    response = requests.get(url, headers=headers)
2254
2255    if response.status_code == 200:
2256        pass
2257    elif response.status_code == 401:
2258        raise ConnectionRefusedError(
2259            "Could not connect. The connection was refused.\n" +
2260            "HTTP Status Code 401."
2261        )
2262    else:
2263        raise ConnectionError(
2264            f"Could not connect.\nHTTP Status code {response.status_code}"
2265        )
2266
2267    json_data = response.json()
2268
2269    if return_as_dict is True:
2270        return json_data
2271
2272    wp_df = pd.json_normalize(json_data)
2273    wp_df.rename(
2274        columns={
2275            "playId": "play_id",
2276            "playText": "play_text",
2277            "homeId": "home_team_id",
2278            "home": "home_team_name",
2279            "awayId": "away_team_id",
2280            "away": "away_team_name",
2281            "spread": "spread_line",
2282            "homeBall": "home_team_on_offense_flag",
2283            "homeScore": "home_score",
2284            "awayScore": "away_score",
2285            "homeWinProb": "home_win_probability",
2286            "playNumber": "play_num",
2287            "yardLine": "yard_line",
2288        },
2289        inplace=True,
2290    )
2291    if len(wp_df) == 0:
2292        logging.error(
2293            "The CFBD API accepted your inputs, "
2294            + "but found no data within your specified input parameters."
2295            + " Please double check your input parameters."
2296        )
2297    else:
2298        wp_df = wp_df.astype({"home_win_probability": "float"})
2299        wp_df["away_win_probability"] = 1 - wp_df["home_win_probability"]
2300
2301    return wp_df

Allows one to get win probability data for a given game ID.

Parameters

game_id (int, mandatory): Mandatory argument. This is the game ID for the game you want win probability data from, at the play-by-play level.

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_game_win_probability_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get the win probability data for a 2017 game between
    # the University of Cincinnati and UConn (game ID #400941851).
    print(
        "Get the win probability data for a 2017 game between " +
        "the University of Cincinnati and UConn (game ID #400941851)."
    )
    json_data = get_cfbd_game_win_probability_data(
        api_key=cfbd_key,
        game_id=400941851
    )
    print(json_data)
    time.sleep(5)

    # Get the win probability data for a 2023 game between
    # the University of Duke and
    # the University of Louisville (game ID #401525535).
    print(
        "Get the win probability data for a 2023 game between " +
        "the University of Duke and " +
        "the University of Louisville (game ID #401525535)."
    )
    json_data = get_cfbd_game_win_probability_data(
        api_key=cfbd_key,
        game_id=401525535
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_game_win_probability_data(
        api_key=cfbd_key,
        game_id=400941851,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded into " +
        "this python environment for this example."
    )

    # Get win probability data for a 2017 game between
    # the University of Cincinnati and UConn (game ID #400941851).
    print(
        "Get the win probability data for a 2017 game between " +
        "the University of Cincinnati and UConn (game ID #400941851)."
    )
    json_data = get_cfbd_game_win_probability_data(
        game_id=400941851
    )
    print(json_data)
    time.sleep(5)

    # Get win probability data for a 2023 game between
    # the University of Duke and
    # the University of Louisville (game ID #401525535).
    print(
        "Get the win probability data for a 2023 game between " +
        "the University of Duke and " +
        "the University of Louisville (game ID #401525535)."
    )
    json_data = get_cfbd_game_win_probability_data(
        game_id=401525535
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return " +
        "the API call as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_game_win_probability_data(
        game_id=400941851,
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with win probability data at the play-by-play level, or (if return_as_dict is set to True) a dictionary object with win probability data at the play-by-play level.

def get_cfbd_pregame_win_probability_data( season: int, api_key: str = None, api_key_dir: str = None, week: int = None, team: str = None, season_type: str = 'regular', return_as_dict: bool = False):
2304def get_cfbd_pregame_win_probability_data(
2305    season: int,
2306    api_key: str = None,
2307    api_key_dir: str = None,
2308    week: int = None,
2309    team: str = None,
2310    season_type: str = "regular",  # "regular" or "postseason"
2311    return_as_dict: bool = False,
2312):
2313    """
2314    Allows you to get pregame win probability data
2315    for games within a time frame.
2316
2317    Parameters
2318    ----------
2319    `api_key` (str, optional):
2320        Semi-optional argument.
2321        If `api_key` is null, this function will attempt to load a CFBD API key
2322        from the python environment, or from a file on this computer.
2323        If `api_key` is not null,
2324        this function will automatically assume that the
2325        inputted `api_key` is a valid CFBD API key.
2326
2327    `api_key_dir` (str, optional):
2328        Optional argument.
2329        If `api_key` is set to am empty string, this variable is ignored.
2330        If `api_key_dir` is null, and `api_key` is null,
2331        this function will try to find
2332        a CFBD API key file in this user's home directory.
2333        If `api_key_dir` is set to a string, and `api_key` is null,
2334        this function will assume that `api_key_dir` is a directory,
2335        and will try to find a CFBD API key file in that directory.
2336
2337    `season` (int, optional):
2338        Semi-optional argument.
2339        Specifies the season you want pregame win probability data.
2340
2341    `week` (int, optional):
2342        Optional argument.
2343        If `week` is set to an integer, this function will attempt
2344        to load CFB game data from games in that season, and in that week.
2345
2346    `team` (str, optional):
2347        Semi-optional argument.
2348        If you only want pregame win probability data for a specific team,
2349        set `team` to the name of the team
2350        you want pregame win probability data from.
2351
2352    `season_type` (str, semi-optional):
2353        Semi-optional argument.
2354        By default, this will be set to "regular", for the CFB regular season.
2355        If you want CFB game information for non-regular season games,
2356        set `season_type` to "postseason".
2357        If `season_type` is set to anything but "regular" or "postseason",
2358        a `ValueError()` will be raised.
2359
2360    `return_as_dict` (bool, semi-optional):
2361        Semi-optional argument.
2362        If you want this function to return the data
2363        as a dictionary (read: JSON object),
2364        instead of a pandas `DataFrame` object,
2365        set `return_as_dict` to `True`.
2366
2367    Usage
2368    ----------
2369    ```
2370    import time
2371
2372    from cfbd_json_py.metrics import get_cfbd_pregame_win_probability_data
2373
2374
2375    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2376
2377    if cfbd_key != "tigersAreAwesome":
2378        print(
2379            "Using the user's API key declared in this script " +
2380            "for this example."
2381        )
2382
2383        # Get pregame win probabilities for games in the 2023 CFB season.
2384        print(
2385            "Get pregame win probabilities for games in the 2023 CFB season."
2386        )
2387        json_data = get_cfbd_pregame_win_probability_data(
2388            api_key=cfbd_key,
2389            season=2023
2390        )
2391        print(json_data)
2392        time.sleep(5)
2393
2394        # Get pregame win probabilities for games
2395        # in week 10 of the 2021 CFB season.
2396        print(
2397            "Get pregame win probabilities for games " +
2398            "in week 10 of the 2021 CFB season."
2399        )
2400        json_data = get_cfbd_pregame_win_probability_data(
2401            api_key=cfbd_key,
2402            season=2021,
2403            week=10
2404        )
2405        print(json_data)
2406        time.sleep(5)
2407
2408
2409        # Get pregame win probabilities for games involving
2410        # the 2021 Cincinnati Bearcats Football Team.
2411        print(
2412            "Get pregame win probabilities for games involving " +
2413            "the 2021 Cincinnati Bearcats Football Team."
2414        )
2415        json_data = get_cfbd_pregame_win_probability_data(
2416            api_key=cfbd_key,
2417            season=2021,
2418            week=10
2419        )
2420        print(json_data)
2421        time.sleep(5)
2422
2423        # Get pregame win probabilities for postseason games
2424        # in the 2020 CFB season.
2425        print(
2426            "Get pregame win probabilities for postseason games " +
2427            "in the 2020 CFB season."
2428        )
2429        json_data = get_cfbd_pregame_win_probability_data(
2430            api_key=cfbd_key,
2431            season=2020,
2432            season_type="postseason"
2433        )
2434        print(json_data)
2435        time.sleep(5)
2436
2437
2438        # You can also tell this function to just return the API call as
2439        # a Dictionary (read: JSON) object.
2440        print(
2441            "You can also tell this function to just return the API call " +
2442            "as a Dictionary (read: JSON) object."
2443        )
2444        json_data = get_cfbd_pregame_win_probability_data(
2445            api_key=cfbd_key,
2446            season=2023,
2447            week=10,
2448            return_as_dict=True
2449        )
2450        print(json_data)
2451
2452    else:
2453        # Alternatively, if the CFBD API key exists in this python environment,
2454        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2455        # you could just call these functions directly,
2456        # without setting the API key in the script.
2457        print(
2458            "Using the user's API key supposedly loaded " +
2459            "into this python environment for this example."
2460        )
2461
2462    # Get pregame win probabilities for games in the 2023 CFB season.
2463        print(
2464            "Get pregame win probabilities for games in the 2023 CFB season."
2465        )
2466        json_data = get_cfbd_pregame_win_probability_data(
2467            season=2023
2468        )
2469        print(json_data)
2470        time.sleep(5)
2471
2472
2473        # Get pregame win probabilities for games
2474        # in week 10 of the 2021 CFB season.
2475        print(
2476            "Get pregame win probabilities for games " +
2477            "in week 10 of the 2021 CFB season."
2478        )
2479        json_data = get_cfbd_pregame_win_probability_data(
2480            season=2021,
2481            week=10
2482        )
2483        print(json_data)
2484        time.sleep(5)
2485
2486
2487        # Get pregame win probabilities for games involving
2488        # the 2021 Cincinnati Bearcats Football Team.
2489        print(
2490            "Get pregame win probabilities for games involving " +
2491            "the 2021 Cincinnati Bearcats Football Team."
2492        )
2493        json_data = get_cfbd_pregame_win_probability_data(
2494            season=2021,
2495            week=10
2496        )
2497        print(json_data)
2498        time.sleep(5)
2499
2500
2501        # Get pregame win probabilities for postseason games
2502        # in the 2020 CFB season.
2503        print(
2504            "Get pregame win probabilities for postseason games" +
2505            " in the 2020 CFB season."
2506        )
2507        json_data = get_cfbd_pregame_win_probability_data(
2508            season=2020,
2509            season_type="postseason"
2510        )
2511        print(json_data)
2512        time.sleep(5)
2513
2514        # You can also tell this function to just return the API call as
2515        # a Dictionary (read: JSON) object.
2516        print(
2517            "You can also tell this function to just return the API call " +
2518            "as a Dictionary (read: JSON) object."
2519        )
2520        json_data = get_cfbd_pregame_win_probability_data(
2521            season=2023,
2522            week=10,
2523            return_as_dict=True
2524        )
2525        print(json_data)
2526
2527    ```
2528    Returns
2529    ----------
2530    A pandas `DataFrame` object with pregame win probability data,
2531    or (if `return_as_dict` is set to `True`)
2532    a dictionary object with a pregame win probability data.
2533
2534    """
2535    now = datetime.now()
2536    wp_df = pd.DataFrame()
2537    # row_df = pd.DataFrame()
2538    url = "https://api.collegefootballdata.com/metrics/wp/pregame"
2539
2540    ##########################################################################
2541
2542    if api_key is not None:
2543        real_api_key = api_key
2544        del api_key
2545    else:
2546        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2547
2548    if real_api_key == "tigersAreAwesome":
2549        raise ValueError(
2550            "You actually need to change `cfbd_key` to your CFBD API key."
2551        )
2552    elif "Bearer " in real_api_key:
2553        pass
2554    elif "Bearer" in real_api_key:
2555        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2556    else:
2557        real_api_key = "Bearer " + real_api_key
2558
2559    if season is None:
2560        pass
2561    elif season > (now.year + 1):
2562        raise ValueError(f"`season` cannot be greater than {season}.")
2563    elif season < 1869:
2564        raise ValueError("`season` cannot be less than 1869.")
2565
2566    if week is not None and week < 0:
2567        raise ValueError("`week` must be an integer greater than 0.")
2568
2569    if season_type != "regular" and season_type != "postseason":
2570        raise ValueError(
2571            '`season_type` must be set to either ' +
2572            '"regular" or "postseason" for this function to work.'
2573        )
2574
2575    # URL builder
2576    ##########################################################################
2577
2578    url_elements = 0
2579
2580    if season is not None and url_elements == 0:
2581        url += f"?year={season}"
2582        url_elements += 1
2583    elif season is not None:
2584        url += f"&year={season}"
2585        url_elements += 1
2586
2587    if week is not None and url_elements == 0:
2588        url += f"?week={week}"
2589        url_elements += 1
2590    elif week is not None:
2591        url += f"&week={week}"
2592        url_elements += 1
2593
2594    if team is not None and url_elements == 0:
2595        url += f"?team={team}"
2596        url_elements += 1
2597    elif team is not None:
2598        url += f"&team={team}"
2599        url_elements += 1
2600
2601    if season_type is not None and url_elements == 0:
2602        url += f"?seasonType={season_type}"
2603        url_elements += 1
2604    elif season_type is not None:
2605        url += f"&seasonType={season_type}"
2606        url_elements += 1
2607
2608    headers = {
2609        "Authorization": f"{real_api_key}", "accept": "application/json"
2610    }
2611
2612    response = requests.get(url, headers=headers)
2613
2614    if response.status_code == 200:
2615        pass
2616    elif response.status_code == 401:
2617        raise ConnectionRefusedError(
2618            "Could not connect. The connection was refused.\n" +
2619            "HTTP Status Code 401."
2620        )
2621    else:
2622        raise ConnectionError(
2623            f"Could not connect.\nHTTP Status code {response.status_code}"
2624        )
2625
2626    json_data = response.json()
2627
2628    if return_as_dict is True:
2629        return json_data
2630
2631    wp_df = pd.json_normalize(json_data)
2632    wp_df.rename(
2633        columns={
2634            "seasonType": "season_type",
2635            "gameId": "game_id",
2636            "homeTeam": "home_team_name",
2637            "awayTeam": "away_team_name",
2638            "spread": "spread_line",
2639            "homeWinProb": "home_win_probability",
2640        },
2641        inplace=True,
2642    )
2643    if len(wp_df) == 0:
2644        logging.error(
2645            "The CFBD API accepted your inputs, "
2646            + "but found no data within your specified input parameters."
2647            + " Please double check your input parameters."
2648        )
2649    else:
2650        wp_df = wp_df.astype({"home_win_probability": "float"})
2651        wp_df["away_win_probability"] = 1 - wp_df["home_win_probability"]
2652
2653    return wp_df

Allows you to get pregame win probability data for games within a time frame.

Parameters

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

season (int, optional): Semi-optional argument. Specifies the season you want pregame win probability data.

week (int, optional): Optional argument. If week is set to an integer, this function will attempt to load CFB game data from games in that season, and in that week.

team (str, optional): Semi-optional argument. If you only want pregame win probability data for a specific team, set team to the name of the team you want pregame win probability data from.

season_type (str, semi-optional): Semi-optional argument. By default, this will be set to "regular", for the CFB regular season. If you want CFB game information for non-regular season games, set season_type to "postseason". If season_type is set to anything but "regular" or "postseason", a ValueError() will be raised.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_pregame_win_probability_data


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get pregame win probabilities for games in the 2023 CFB season.
    print(
        "Get pregame win probabilities for games in the 2023 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        api_key=cfbd_key,
        season=2023
    )
    print(json_data)
    time.sleep(5)

    # Get pregame win probabilities for games
    # in week 10 of the 2021 CFB season.
    print(
        "Get pregame win probabilities for games " +
        "in week 10 of the 2021 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        api_key=cfbd_key,
        season=2021,
        week=10
    )
    print(json_data)
    time.sleep(5)


    # Get pregame win probabilities for games involving
    # the 2021 Cincinnati Bearcats Football Team.
    print(
        "Get pregame win probabilities for games involving " +
        "the 2021 Cincinnati Bearcats Football Team."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        api_key=cfbd_key,
        season=2021,
        week=10
    )
    print(json_data)
    time.sleep(5)

    # Get pregame win probabilities for postseason games
    # in the 2020 CFB season.
    print(
        "Get pregame win probabilities for postseason games " +
        "in the 2020 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        api_key=cfbd_key,
        season=2020,
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        api_key=cfbd_key,
        season=2023,
        week=10,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded " +
        "into this python environment for this example."
    )

# Get pregame win probabilities for games in the 2023 CFB season.
    print(
        "Get pregame win probabilities for games in the 2023 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        season=2023
    )
    print(json_data)
    time.sleep(5)


    # Get pregame win probabilities for games
    # in week 10 of the 2021 CFB season.
    print(
        "Get pregame win probabilities for games " +
        "in week 10 of the 2021 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        season=2021,
        week=10
    )
    print(json_data)
    time.sleep(5)


    # Get pregame win probabilities for games involving
    # the 2021 Cincinnati Bearcats Football Team.
    print(
        "Get pregame win probabilities for games involving " +
        "the 2021 Cincinnati Bearcats Football Team."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        season=2021,
        week=10
    )
    print(json_data)
    time.sleep(5)


    # Get pregame win probabilities for postseason games
    # in the 2020 CFB season.
    print(
        "Get pregame win probabilities for postseason games" +
        " in the 2020 CFB season."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        season=2020,
        season_type="postseason"
    )
    print(json_data)
    time.sleep(5)

    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_pregame_win_probability_data(
        season=2023,
        week=10,
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with pregame win probability data, or (if return_as_dict is set to True) a dictionary object with a pregame win probability data.

def get_cfbd_fg_expected_points( api_key: str = None, api_key_dir: str = None, return_as_dict: bool = False):
2656def get_cfbd_fg_expected_points(
2657    api_key: str = None, api_key_dir: str = None, return_as_dict: bool = False
2658):
2659    """
2660    Retrieves Expected Points data for field goals from the CFBD API.
2661
2662    Parameters
2663    ----------
2664    `api_key` (str, optional):
2665        Semi-optional argument.
2666        If `api_key` is null, this function will attempt to load a CFBD API key
2667        from the python environment, or from a file on this computer.
2668        If `api_key` is not null,
2669        this function will automatically assume that the
2670        inputted `api_key` is a valid CFBD API key.
2671
2672    `api_key_dir` (str, optional):
2673        Optional argument.
2674        If `api_key` is set to am empty string, this variable is ignored.
2675        If `api_key_dir` is null, and `api_key` is null,
2676        this function will try to find
2677        a CFBD API key file in this user's home directory.
2678        If `api_key_dir` is set to a string, and `api_key` is null,
2679        this function will assume that `api_key_dir` is a directory,
2680        and will try to find a CFBD API key file in that directory.
2681
2682    `return_as_dict` (bool, semi-optional):
2683        Semi-optional argument.
2684        If you want this function to return the data
2685        as a dictionary (read: JSON object),
2686        instead of a pandas `DataFrame` object,
2687        set `return_as_dict` to `True`.
2688
2689    Usage
2690    ----------
2691    ```
2692    import time
2693
2694    from cfbd_json_py.metrics import get_cfbd_fg_expected_points
2695
2696
2697    cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.
2698
2699    if cfbd_key != "tigersAreAwesome":
2700        print(
2701            "Using the user's API key declared in this script " +
2702            "for this example."
2703        )
2704
2705        # Get Expected Points (EP) data, specifically for field goals,
2706        # from the CFBD API.
2707        print(
2708            "Get Expected Points (EP) data, specifically for " +
2709            "field goals, from the CFBD API."
2710        )
2711        json_data = get_cfbd_fg_expected_points(
2712            api_key=cfbd_key,
2713        )
2714        print(json_data)
2715        time.sleep(5)
2716
2717
2718        # You can also tell this function to just return the API call as
2719        # a Dictionary (read: JSON) object.
2720        print(
2721            "You can also tell this function to just return the API call " +
2722            "as a Dictionary (read: JSON) object."
2723        )
2724        json_data = get_cfbd_fg_expected_points(
2725            api_key=cfbd_key,
2726            return_as_dict=True
2727        )
2728        print(json_data)
2729
2730    else:
2731        # Alternatively, if the CFBD API key exists in this python environment,
2732        # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
2733        # you could just call these functions directly,
2734        # without setting the API key in the script.
2735        print(
2736            "Using the user's API key supposedly loaded " +
2737            "into this python environment for this example."
2738        )
2739
2740        # Get Expected Points (EP) data,
2741        # specifically for field goals, from the CFBD API.
2742        print(
2743            "Get Expected Points (EP) data, " +
2744            "specifically for field goals, from the CFBD API."
2745        )
2746        json_data = get_cfbd_fg_expected_points()
2747        print(json_data)
2748        time.sleep(5)
2749
2750
2751        # You can also tell this function to just return the API call as
2752        # a Dictionary (read: JSON) object.
2753        print(
2754            "You can also tell this function to just return the API call " +
2755            "as a Dictionary (read: JSON) object."
2756        )
2757        json_data = get_cfbd_fg_expected_points(
2758            return_as_dict=True
2759        )
2760        print(json_data)
2761    ```
2762
2763    Returns
2764    ----------
2765    A pandas `DataFrame` object with Expected Points data for field goals,
2766    or (if `return_as_dict` is set to `True`)
2767    a dictionary object with Expected Points data for field goals.
2768
2769    """
2770    epa_df = pd.DataFrame()
2771    # row_df = pd.DataFrame()
2772    url = "https://api.collegefootballdata.com/metrics/fg/ep"
2773
2774    # Input validation
2775    ##########################################################################
2776
2777    if api_key is not None:
2778        real_api_key = api_key
2779        del api_key
2780    else:
2781        real_api_key = get_cfbd_api_token(api_key_dir=api_key_dir)
2782
2783    if real_api_key == "tigersAreAwesome":
2784        raise ValueError(
2785            "You actually need to change `cfbd_key` to your CFBD API key."
2786        )
2787    elif "Bearer " in real_api_key:
2788        pass
2789    elif "Bearer" in real_api_key:
2790        real_api_key = real_api_key.replace("Bearer", "Bearer ")
2791    else:
2792        real_api_key = "Bearer " + real_api_key
2793
2794    headers = {
2795        "Authorization": f"{real_api_key}", "accept": "application/json"
2796    }
2797
2798    response = requests.get(url, headers=headers)
2799
2800    if response.status_code == 200:
2801        pass
2802    elif response.status_code == 401:
2803        raise ConnectionRefusedError(
2804            "Could not connect. The connection was refused.\n" +
2805            "HTTP Status Code 401."
2806        )
2807    else:
2808        raise ConnectionError(
2809            f"Could not connect.\nHTTP Status code {response.status_code}"
2810        )
2811
2812    json_data = response.json()
2813
2814    if return_as_dict is True:
2815        return json_data
2816
2817    epa_df = pd.json_normalize(json_data)
2818    epa_df.rename(
2819        columns={
2820            "yardsToGoal": "yards_to_goal",
2821            "expectedPoints": "expected_points",
2822        },
2823        inplace=True,
2824    )
2825    return epa_df

Retrieves Expected Points data for field goals from the CFBD API.

Parameters

api_key (str, optional): Semi-optional argument. If api_key is null, this function will attempt to load a CFBD API key from the python environment, or from a file on this computer. If api_key is not null, this function will automatically assume that the inputted api_key is a valid CFBD API key.

api_key_dir (str, optional): Optional argument. If api_key is set to am empty string, this variable is ignored. If api_key_dir is null, and api_key is null, this function will try to find a CFBD API key file in this user's home directory. If api_key_dir is set to a string, and api_key is null, this function will assume that api_key_dir is a directory, and will try to find a CFBD API key file in that directory.

return_as_dict (bool, semi-optional): Semi-optional argument. If you want this function to return the data as a dictionary (read: JSON object), instead of a pandas DataFrame object, set return_as_dict to True.

Usage

import time

from cfbd_json_py.metrics import get_cfbd_fg_expected_points


cfbd_key = "tigersAreAwesome"  # placeholder for your CFBD API Key.

if cfbd_key != "tigersAreAwesome":
    print(
        "Using the user's API key declared in this script " +
        "for this example."
    )

    # Get Expected Points (EP) data, specifically for field goals,
    # from the CFBD API.
    print(
        "Get Expected Points (EP) data, specifically for " +
        "field goals, from the CFBD API."
    )
    json_data = get_cfbd_fg_expected_points(
        api_key=cfbd_key,
    )
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_fg_expected_points(
        api_key=cfbd_key,
        return_as_dict=True
    )
    print(json_data)

else:
    # Alternatively, if the CFBD API key exists in this python environment,
    # or it's been set by cfbd_json_py.utls.set_cfbd_api_token(),
    # you could just call these functions directly,
    # without setting the API key in the script.
    print(
        "Using the user's API key supposedly loaded " +
        "into this python environment for this example."
    )

    # Get Expected Points (EP) data,
    # specifically for field goals, from the CFBD API.
    print(
        "Get Expected Points (EP) data, " +
        "specifically for field goals, from the CFBD API."
    )
    json_data = get_cfbd_fg_expected_points()
    print(json_data)
    time.sleep(5)


    # You can also tell this function to just return the API call as
    # a Dictionary (read: JSON) object.
    print(
        "You can also tell this function to just return the API call " +
        "as a Dictionary (read: JSON) object."
    )
    json_data = get_cfbd_fg_expected_points(
        return_as_dict=True
    )
    print(json_data)

Returns

A pandas DataFrame object with Expected Points data for field goals, or (if return_as_dict is set to True) a dictionary object with Expected Points data for field goals.