Skip to content

Repository files navigation

AP College Football Cross-Country Scoring

A Data-Driven Approach to Determining Conference Supremacy

Generic badge Python versions Code style: black

This repository implements a novel method for evaluating the best college football conferences using a cross-country scoring mechanism. This method ranks conferences based on the positions of their top teams in the Associated Press's Top 25 rankings before, throughout, and at the end of each college football season. This provides an objective, measurable comparison of conference strength for every week of the season.

Current Results

5-Team

five team

4-Team

four team

Background

Inspired by the team scoring in cross-country racing, this method sums the "finishing positions," or the ranking, of the top five teams within each conference. The conference with the lowest total score is deemed the best, emphasizing overall depth and strength rather than just top-tier performance (like whichever conference produced the most recent national champion, or bogus math like detailed in the below tweet).

Take a look at the average AP Ranking by Power Five Conference 📊

Which conference surprises you the most? 👀 pic.twitter.com/qJ0AWkQkOm

— FOX College Football (@CFBONFOX) January 18, 2023

This approach was first introduced in 2015 and updated in 2019 and 2024. You can read more about the method and its evolution in the following blog posts:

The results of this work across every season on record, tracking each conference's Final AP ranking score by year: Results_Graph

This code is built upon the ESPN College Football API, shown by Akshay Easwaran to have hidden endpoints with reliable AP ranking information back to 2014. Thus, this code is dependent upon the quality and stability of ESPN's API data structure.

Repository Structure

  • data: Input/output data, organized as data/<year>/<4_team|5_team>/. Each subdirectory holds one CSV per week (<year>_week_<N>.csv) plus one running <year>_<4_team|5_team>_summary_statistics.csv that accumulates every week's conference scores for that season.
  • images: Auto-generated graph PNGs referenced by this README. These are overwritten in place each time the graphing scripts run (see Graphing below) - don't hand-edit them.
  • espn_api.py: Script for fetching data from the ESPN API.
  • store_data.py: Script for storing data fetched from external sources.
  • graph_data.py: Generates the styled graphs shown in this README, both for a single season and across every season on record (see "Graphing" under Specialized Uses below).
  • weekly_update.py: One-shot entry point that pulls the latest rankings and regenerates the current-week graphs in a single call - see Automating Weekly Updates.
  • counterfactual_conferences_2023.py: Standalone "what-if" script remapping 2023 results onto the 2024 realigned conferences.

Python Environments

Make sure all required packages are installed. You can do this in a few ways:

1) Install to Base Interpreter

Using your command line or bash terminal:

pip install -r requirements.in

This will install the package's dependencies to your base python interpreter. This is not recommended as other python projects or repositories may require different versions of these packages.

requirements.in lists the packages this project actually needs, with any version pins kept deliberate and minimal (e.g. a security-floor minimum version). requirements.txt, by contrast, is a full pip freeze snapshot of a known-working environment - useful as a reference if you hit a dependency conflict, but not what you should install from directly.

2) Virtual Environments

Setting up a virtual python environment (venv) is recommended to ensure no dependency conflicts across your personal projects or with other developers on this project. See below for executing this on windows operating systems.

Usage

To execute a full run that pulls the latest AP rankings from ESPN and scores them as a cross-country meet, execute and run the store_data.py file.

Automating Weekly Updates

weekly_update.py is a single entry point that does the whole week's work in one call: it fetches and stores the latest AP rankings for both 4-team and 5-team scoring, then regenerates images/current_week_4team.png and images/current_week_5team.png - the same filenames this README links to above, so a new week's results show up here automatically with no README edits needed.

Run it directly with your venv's interpreter:

python weekly_update.py

For unattended/scheduled runs, use the wrapper script for your OS instead of calling weekly_update.py directly. Both scripts locate the project's venv relative to their own location - no machine-specific paths to edit - and exit with a clear error if no venv is found rather than silently falling back to a different interpreter:

  • Windows: weekly_update.bat - point a Task Scheduler (schtasks) job at this file.
  • Linux/macOS/WSL/Git Bash: weekly_update.sh - point a cron job at this file. It also works against a Windows-created venv when run from WSL or Git Bash.

Neither script pauses for input by default, so they're safe to run unattended; each has a commented-out pause (Windows) / read (Linux) line you can uncomment if you'd rather the window stay open when running it manually by double-click.

Specialized Uses

  1. Fetch Data:

    • Use espn_api.py to fetch the latest college football data from ESPN.

    • Critical Functions:

      • full_ap_xc_run(year: int = None, week=None, four_team_score: bool = False) -> dict

        Purpose: Fetches the full AP cross-country run data for a given year and week, with an option for four-team scoring.

        Inputs:

        • year: The year for which to fetch data (optional).
        • week: The week for which to fetch data (optional).
        • four_team_score: Boolean indicating whether to use four-team scoring (default is False).

        Outputs:

        • A dictionary containing the fetched data, including conference team data and conference scores.
  2. Store Data:

    • Use store_data.py to store the fetched data into a suitable format for analysis.

    • Critical Functions:

      • summarize_data(week, conference_score_tuple: list, n_teams_str: str = pent, existing_summary_df: pd.DataFrame = None)

        Purpose: Summarizes data for a given week and conference score tuple. It standardizes the week formatting, handles potential errors, and writes the summary data to a file.

        Inputs:

        • week: The week to summarize.
        • conference_score_tuple: List of conference scores.
        • n_teams_str: String indicating the number of teams (default is pent).
        • existing_summary_df: Existing summary DataFrame (optional).

        Outputs:

        • The summary data as a DataFrame.
      • store_weekly_results(year: int = None, week=None, four_team_score: bool = False)

        Purpose: Stores weekly results by calling various functions to fetch, prepare, and write data.

        Inputs:

        • year: The year to store results for (optional).
        • week: The week to store results for (optional).
        • four_team_score: Boolean indicating whether to use four-team scoring (default is False).

        Outputs:

        • The results of the storage operation.
      • store_all_data_2014_to_present()

        Purpose: Stores all data from 2014 to the present year by iterating through each year and week, calling store_weekly_results for both four-team and five-team scoring.

        Inputs: None

        Outputs: None

  3. Counterfactual Conference Analysis:

    • Use counterfactual_conferences_2023.py to impose the 2024 conference membership schema onto the 2023 season results, previewing how the realigned conferences could perform in 2024.

    • Critical Functions:

      • realign_teams(df: pd.DataFrame, n_teams_score: int = 5)

        Purpose: Realigns teams based on the 2024 conference membership schema and recalculates their standings using the 2023 season results. This function previews the future strength of each conference under the upcoming realignments.

        Inputs:

        • df: DataFrame containing the 2023 season results.
        • n_teams_score: The number of top team scores to sum for each conference (default is 5).

        Outputs:

        • A DataFrame with teams realigned to their new conferences and the recalculated conference standings.
  4. Graphing:

    • Use graph_data.py to turn a season's (or every season's) stored summary statistics into the styled, halogen-glow graphs shown at the top of this README.

    • Critical Functions:

      • graph_year(year: int, num_scoring_teams: int = 5, show: bool = True)

        Purpose: Plots one season's weekly conference scores, Preseason through Final.

        Inputs:

        • year: The season to graph.
        • num_scoring_teams: 4 or 5; which scoring mode's data to plot (default 5).
        • show: Whether to pop open a plot window (default True; set False for unattended runs).

        Outputs:

        • The matplotlib.pyplot module, with the generated figure as its current figure.
      • graph_final_rankings_by_year(num_scoring_teams: int = 5, show: bool = True)

        Purpose: Plots each conference's Final-week score across every season on record - one point per year - so you can see a conference's ranking trend over time rather than within one season.

        Inputs: Same as graph_year, minus year (it covers every season found under data/).

        Outputs:

        • The matplotlib.pyplot module, as above.
      • save_graph(plot, file_name: str = None) -> str

        Purpose: Saves a graph produced by the functions above to images/, creating that directory if needed. If file_name is omitted, it's derived from the graph's own title.

        Inputs:

        • plot: The return value of graph_year() / graph_final_rankings_by_year().
        • file_name: Output filename (optional).

        Outputs:

        • The full path the image was saved to.
    • Conference line colors follow a fixed, deliberate convention (defined in CONFERENCE_COLORS in graph_data.py): SEC is blue, Big Ten is yellow, ACC is red, Big 12 is purple, the American (AAC) is orange - reserved even though it rarely fields enough ranked teams to score - and the defunct Pac-12 is light blue, since it still appears throughout the historical data. Any other conference that shows up (Mountain West, Sun Belt, MAC, etc.) is colored from a rotating fallback palette, since no fixed color has ever been established for them.

Contributing

Contributions are welcome! Please fork the repository and create a pull request with your changes.

Thanks to John-Lee-Cooper, seanreid5454, & akeaswaran for their thought partnership and good ideas over the years on this project.

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

About

Python-based program to pull the AP NCAA college football rankings and score them in a cross-country race style to determine the best football conference in a given week.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages