HW02
Anonymous
python
02/27/2026 11:52 PM
13.5 KB
14
Indexable
"""
Name: Sebastian Brookes
Course: DS 2500
Assignment: Homework 2
Date: 2026-02-27
Filename: 02.py
"""
import csv
import math
import matplotlib.pyplot as plt
DATA_FILE = "wsl_goals_2324.csv"
ABBR_MAP = {
"Arsenal": "ARS",
"Aston Villa": "AVL",
"Brighton and Hove Albion": "BHA",
"Bristol City": "BCFC",
"Chelsea": "CHEE",
"Everton": "EFC",
"Leicester City": "LCFC",
"Liverpool": "LFC",
"Manchester City": "MCFC",
"Manchester United": "MUFC",
"Tottenham Hotspur": "THFC",
"West Ham United": "WHU"
}
SEPARATOR = "=" * 40
COLOR_MAP = {
"Arsenal": "red",
"Aston Villa": "lightskyblue",
"Brighton and Hove Albion": "mediumblue",
"Bristol City": "darkred",
"Chelsea": "blue",
"Everton": "darkblue",
"Leicester City": "orange",
"Liverpool": "orangered",
"Manchester City": "steelblue",
"Manchester United": "yellow",
"Tottenham Hotspur": "navy",
"West Ham United": "brown"
}
# PART 01
class Team:
def __init__(self, name):
self.name = name
self.goals = []
def add_goals(self, goals):
"""
Parameters: an int of goals scored in a game
Returns: nothing
Does: appends the given goal count to the
team's list of goals
"""
self.goals.append(goals)
def get_total_goals(self):
"""
Parameters: nothing
Returns: an int
Does: computes and returns the total number
of goals across all games
"""
return sum(self.goals)
def __str__(self):
"""
Parameters: nothing
Returns: a string
Does: returns a string with the team name and
their total number of goals
"""
return f"{self.name} has scored {self.get_total_goals()} goals."
def read_data(file):
"""
Parameters: a string filepath to a CSV file
Returns: a list of Team objects
Does: reads the CSV file and creates a Team object
for each row, adding goal counts per game
"""
with open(file, "r", encoding="utf-8") as f:
reader = csv.reader(f)
next(reader)
teams = []
for row in reader:
team = Team(row[0])
for goal in row[1:]:
if goal == "":
team.add_goals(0)
else:
team.add_goals(int(goal))
teams.append(team)
return teams
# PART 02
# 2.1
def get_team_with_most_goals(teams):
"""
Parameters: a list of Team objects
Returns: a tuple of (team_name, total_goals)
Does: finds and returns the team with the highest
total number of goals
"""
most_goals = 0
best_team_name = ""
for team in teams:
total = team.get_total_goals()
if total > most_goals:
most_goals = total
best_team_name = team.name
return (best_team_name, most_goals)
# 2.2
def get_mean_season_goals(teams):
"""
Parameters: a list of Team objects
Returns: a float
Does: computes and returns the mean total goals
scored across all teams in a session
"""
total_goals = sum(team.get_total_goals() for team in teams)
return total_goals / len(teams)
# 2.3
def get_variance_season_goals(teams):
"""
Parameters: a list of Team objects
Returns: a float
Does: computes and returns the variance of total
goals scored across all teams in a session
"""
mean = get_mean_season_goals(teams)
squared_diffs = [(team.get_total_goals() - mean) ** 2 for team in teams]
return sum(squared_diffs) / len(squared_diffs)
# 2.4
def get_standard_deviation_season_goals(teams):
"""
Parameters: a list of Team objects
Returns: a float
Does: computes and returns the standard deviation
of total goals across all teams in a session
"""
return math.sqrt(get_variance_season_goals(teams))
# 2.5
def get_median_for_team(name, teams):
"""
Parameters: a string team name and a list of Team objects
Returns: a float
Does: finds the given team and computes and returns
the median goals scored per game
"""
for team in teams:
if name == team.name:
sorted_goals = sorted(team.goals)
n = len(sorted_goals)
mid = n // 2
if n % 2 == 1:
return sorted_goals[mid]
else:
return (sorted_goals[mid] + sorted_goals[mid - 1]) / 2
# 2.6
def get_mode_for_team(name, teams):
"""
Parameters: a string team name and a list of Team objects
Returns: an int
Does: finds the given team and computes and returns
the most frequently occurring goals per game
"""
goal_freq = {}
for team in teams:
if name == team.name:
for count in team.goals:
goal_freq[count] = goal_freq.get(count, 0) + 1
return max(goal_freq, key=lambda x: goal_freq[x])
# 2.7
def get_most_consistent_team(teams):
"""
Parameters: a list of Team objects
Returns: a tuple of (team_name, coefficient_of_variation)
Does: finds and returns the team with the lowest
coefficient of variation (std dev / mean)
"""
cv_by_team = {}
for team in teams:
team_mean = team.get_total_goals() / len(team.goals)
squared_diffs = [(game - team_mean) ** 2 for game in team.goals]
team_stdev = math.sqrt(sum(squared_diffs) / len(squared_diffs))
cv = team_stdev / team_mean
cv_by_team[team.name] = cv
consistent_team_name = min(cv_by_team, key=lambda x: cv_by_team[x])
return (consistent_team_name, cv_by_team[consistent_team_name])
# 2.8
def get_longest_streak_team(teams):
"""
Parameters: a list of Team objects
Returns: a tuple of (team_name, streak_length)
Does: finds and returns the team with the longest
streak of games scoring 2 or more goals
"""
best_team_streak = 0
best_team_name = ""
for team in teams:
streak = 0
team_streak = 0
for game in team.goals:
if game >= 2:
streak += 1
if streak > team_streak:
team_streak = streak
else:
streak = 0
if team_streak > best_team_streak:
best_team_streak = team_streak
best_team_name = team.name
return (best_team_name, best_team_streak)
# 2.9
def get_most_improved_mean_goals_team(teams):
"""
Parameters: a list of Team objects
Returns: a tuple of (team_name, improvement)
Does: finds and returns the team that improved their
mean goals per game the most from the first
half to the second half of the season
"""
best_name = ""
best_improvement = float("-inf")
for team in teams:
mid = len(team.goals) // 2
first_half_mean = sum(team.goals[:mid]) / mid
second_half_mean = sum(team.goals[mid:]) / (len(team.goals) - mid)
improvement = second_half_mean - first_half_mean
if improvement > best_improvement:
best_improvement = improvement
best_name = team.name
return (best_name, best_improvement)
# 2.10
def plot_teams(teams):
"""
Parameters: a list of Team objects
Returns: nothing
Does: generates an animated scatter plot of each
team's cumulative goal progression throughout
the season
"""
for game_num in range(len(teams[0].goals)):
plt.clf()
for i, team in enumerate(teams):
cumulative = sum(team.goals[:game_num + 1])
plt.scatter(cumulative, i,
color=COLOR_MAP[team.name],
label=team.name)
plt.legend(bbox_to_anchor=(1.05, 1),
loc="upper left")
plt.tight_layout(rect=[0.05, 0, 1, 0.95])
max_goals = max(t.get_total_goals() for t in teams)
plt.xlim(0, max_goals)
labels = [ABBR_MAP[t.name] for t in teams]
plt.yticks(range(len(teams)), labels)
plt.title("Progression of Teams")
plt.xlabel("Goals")
plt.ylabel("Team")
plt.pause(0.75)
plt.show()
def print_section(label, result, separator):
"""
Parameters: a string label, a string result, and
a string separator
Returns: nothing
Does: prints a labeled section wrapped in separator
lines
"""
print(separator)
print(label)
print(separator)
print(result, "\n")
def main():
"""
Parameters: nothing
Returns: nothing
Does: reads data, prints analysis results, and
generates a progression plot
"""
teams = read_data(DATA_FILE)
sep = SEPARATOR
print_section("Problem 2.1",
f"Team with most goals: "
f"{get_team_with_most_goals(teams)}",
sep)
print_section("Problem 2.2",
f"Mean: "
f"{get_mean_season_goals(teams)}",
sep)
print_section("Problem 2.3",
f"Variance: "
f"{get_variance_season_goals(teams)}",
sep)
print_section("Problem 2.4",
f"Std dev: "
f"{get_standard_deviation_season_goals(teams)}",
sep)
arsenal_median = get_median_for_team("Arsenal", teams)
print_section("Problem 2.5",
f"Arsenal median goals: "
f"{arsenal_median}",
sep)
spurs_mode = get_mode_for_team("Tottenham Hotspur",
teams)
print_section("Problem 2.6",
f"Tottenham mode goals: "
f"{spurs_mode}",
sep)
print_section("Problem 2.7",
f"Most consistent team: "
f"{get_most_consistent_team(teams)}",
sep)
print_section("Problem 2.8",
f"Longest streak overall: "
f"{get_longest_streak_team(teams)}",
sep)
most_improved = get_most_improved_mean_goals_team(teams)
print_section("Problem 2.9",
f"Team with best improvement: "
f"{most_improved}",
sep)
plot_teams(teams)
if __name__ == "__main__":
main()
Editor is loading...
Leave a Comment