Performance Analytics Final Project FA25 ¶
Faye Coy and Ava Weisheit ¶
How Has Catilin Clark Influenced WNBA Attendance? ¶
Part 1 : Who is Catlin Clark ¶
“People say that Caitlin Clark moves the needle. That is wrong. She is the needle., she dictates” said Chiney Ogunmike said while reporting on the 2025 WNBA All-Star Weekend. It’s clear that Caitlin Clark has made an impact on the Indiana Fever and the WNBA, as She and her team accounted for 45% of all the broadcast value of the WNBA in the 2024 season, again stated by Ogunmike in the same segment. With all the brand deals and jersey sell-outs, her impact both on and off the floor has been widely discussed. Her involvement with the Indiana Fever has dramatically changed their numbers and profits, but we wanted to investigate how Caitlin Clark has affected basketball leaguewide. Because so much talk around the athlete has been widespread on our phones, we wanted to conduct a data analysis based on the question “Can Caitlin Clark’s impact be seen when just overviewing attendance data?”
As a way to determine her impact, we looked at attendance data from the past 5 seasons as well as Google Trends data throughout the years to demonstrate media outreach. These numbers of course have many other outliers that we hope to address while analyzing our data including COVID and additions of new teams.
As a comparison, we used #20 Point Guard for the New York Liberty, Sabrina Ionescu to really demonstrate how the WNBA operated in previous years. Caitlin Clark and Sabrina Ionescu could even be seen as similar players. Both has stellar college careers which led them to be the #1 overall draft pick for the league, and both stars were given shoe deals and had gathered some fame for their playstyles on the court.
Part 2 : Data Sources ¶
import pandas as pd
from pytrends.request import TrendReq
import matplotlib.pyplot as plt
%matplotlib inline
import random
import numpy as np
from scipy import stats
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
import pandas as pd
from pandasql import sqldf
We had access to a csv file of WNBA attendance from 1997-2025.
The dataset contains game-level attendance data from the WNBA, including: Year of the game (2023–2024), Day of the week and date (Month/Day), Game time (ET), Game type (Regular season, Playoffs, etc.), Home team and away team, Arena, city, and state, and Reported attendance (numeric).
This is structured numerical and categorical data, suitable for analysis, visualization, and correlation with other indicators.
Our initial plan was to compare Google trends data to see if increased online searches about Caitliin Clark or the Indiana Fever would correlate with increased attendance.
Here we remove unwanted index columns in our attendance data and limit the years to 2022-2025. We chose to do this because WNBA attendance started increasing after Covid in 2020 and Indiana did not have home games at their arena in 2021.
attendance_df = pd.read_csv("attendance.csv")
# Filter only 2023 - 2024 seasons
attendance_cleaned = attendance_df[attendance_df["Year"].isin([2022, 2023, 2024, 2025])].copy()
# Drop any unwanted index columns if present
if "Unnamed: 0" in attendance_cleaned.columns:
attendance_cleaned = attendance_cleaned.drop(columns=["Unnamed: 0"])
# Create new column of date-time
attendance_cleaned['date'] = pd.to_datetime(
attendance_df['Month'] + ' ' +
attendance_df['Day'].astype(str) + ', ' +
attendance_df['Year'].astype(str)
)
# Save the cleaned version
attendance_cleaned.to_csv("Attendance_2022-2025.csv", index=False)
print("Cleaned file saved as Attendance_2022-2025.csv")
attendance_cleaned.head(2)
Cleaned file saved as Attendance_2022-2025.csv
| Year | Day of Week | Month | Day | Time (ET) | Game Type | Home Team | Away Team | Arena | City | State | Attendance | date | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5450 | 2022 | Friday | May | 6 | 7:00 PM | Regular season | Washington Mystics | Indiana Fever | Entertainment and Sports Arena | Washington | DC | 4200 | 2022-05-06 |
| 5451 | 2022 | Friday | May | 6 | 8:00 PM | Regular season | Chicago Sky | Los Angeles Sparks | Wintrust Arena | Chicago | IL | 8111 | 2022-05-06 |
In the following code we use google trends data API to scrape data. Google Trends data shows the relative popularity of search terms over time, in different regions, and across different Google properties. It reveals the relative search interest on a scale of 0-100, where 100 is the peak popularity for a given time frame and location.
Here we used keywords "Caitlin Clark" and "Indiana Fever" from 2021-2025 and in Indiana only to create a df about Google Trends data for Indiana Fever. We did the same for New York Liberty except looking strictly in New York. We then merged the dataframes on date to create one collective df on Google Trends for both Fever and Liberty.
pytrends = TrendReq(hl='en-US', tz=360)
keywords = ["Caitlin Clark", "Indiana Fever"]
# Add error handling for the API request
try:
pytrends.build_payload(kw_list=keywords, timeframe='2021-01-04 2025-10-10', geo='US')
trends_df = pytrends.interest_over_time().reset_index()
# Drop 'isPartial' column if present
if 'isPartial' in trends_df.columns:
trends_df = trends_df.drop(columns=['isPartial'])
# Save data
trends_df.to_csv("fever_trends.csv", index=False)
print("Cleaned file saved as fever_trends.csv")
display(trends_df.head())
except Exception as e:
print(f"An error occurred: {e}")
Cleaned file saved as fever_trends.csv
| date | Caitlin Clark | Indiana Fever | |
|---|---|---|---|
| 0 | 2021-01-03 | 0 | 0 |
| 1 | 2021-01-10 | 0 | 0 |
| 2 | 2021-01-17 | 0 | 0 |
| 3 | 2021-01-24 | 0 | 0 |
| 4 | 2021-01-31 | 0 | 0 |
pytrends = TrendReq(hl='en-US', tz=360)
keywords = ["Sabrina Ionescu", "New York Liberty"]
# Add error handling for the API request
try:
pytrends.build_payload(kw_list=keywords, timeframe='2021-01-04 2025-10-10', geo='US')
liberty_trends_df = pytrends.interest_over_time().reset_index()
# Drop 'isPartial' column if present
if 'isPartial' in liberty_trends_df.columns:
liberty_trends_df = liberty_trends_df.drop(columns=['isPartial'])
# Save data
liberty_trends_df.to_csv("liberty_trends.csv", index=False)
print("Cleaned file saved as liberty_trends.csv")
display(liberty_trends_df.head())
except Exception as e:
print(f"An error occurred: {e}")
An error occurred: The request failed: Google returned a response with code 429
In the folowing code, we are going through the data and converting dates to date-time so that both attendance rates and google trends data can be easily plotted with one another.
We also had an issue where google trends data makes a report on each sunday of every week, whereas attendance rates are recored during gamedays during the week. We combated this by taking an average attendance each week to make sure that the date-time alligned for both atendance and google trends.
Fiinally, we created a dataframe for both the liberty and fever that contained the date in date-time form, the average weekly attendace rate, and the google trend score of each Caitlin Clark/Indiana Fever and Sabrina Ionescu/New York Liberty.
# Load attendance data
df = pd.read_csv('Attendance_2022-2025.csv')
# Filter home games
liberty_home = df[df['Home Team'] == 'New York Liberty'].copy()
fever_home = df[df['Home Team'] == 'Indiana Fever'].copy()
# Convert 'Date' to datetime and set as index
liberty_home['date'] = pd.to_datetime(liberty_home['date'])
liberty_home.set_index('date', inplace=True)
fever_home['date'] = pd.to_datetime(fever_home['date'])
fever_home.set_index('date', inplace=True)
# Aggregate attendance per week (mean per game)
fever_attendance_weekly = fever_home['Attendance'].resample('W-MON').mean()
liberty_attendance_weekly = liberty_home['Attendance'].resample('W-MON').mean()
# Load Google Trends data
libertytrends_df = pd.read_csv('liberty_trends.csv')
indianatrends_df = pd.read_csv('fever_trends.csv')
# Convert date to datetime and set as index
libertytrends_df['date'] = pd.to_datetime(libertytrends_df['date'])
libertytrends_df.set_index('date', inplace=True)
indianatrends_df['date'] = pd.to_datetime(indianatrends_df['date'])
indianatrends_df.set_index('date', inplace=True)
# Resample weekly (just to be safe)
liberty_trends_weekly = libertytrends_df['New York Liberty'].resample('W-MON').mean()
ionescu_trends_weekly = libertytrends_df['Sabrina Ionescu'].resample('W-MON').mean()
trends_weekly = indianatrends_df['Indiana Fever'].resample('W-MON').mean()
clark_trends_weekly = indianatrends_df['Caitlin Clark'].resample('W-MON').mean()
# Merge weekly data: attendance + team trends + player trends
fever_weekly_data = pd.merge(fever_attendance_weekly, trends_weekly, left_index=True, right_index=True)
fever_weekly_data = pd.merge(fever_weekly_data, clark_trends_weekly, left_index=True, right_index=True)
liberty_weekly_data = pd.merge(liberty_attendance_weekly, liberty_trends_weekly, left_index=True, right_index=True)
liberty_weekly_data = pd.merge(liberty_weekly_data, ionescu_trends_weekly, left_index=True, right_index=True)
liberty_weekly_data.head()
| Attendance | New York Liberty | Sabrina Ionescu | |
|---|---|---|---|
| date | |||
| 2022-05-09 | 6829.0 | 9.0 | 2.0 |
| 2022-05-16 | 3192.0 | 8.0 | 1.0 |
| 2022-05-23 | 3054.0 | 8.0 | 1.0 |
| 2022-05-30 | NaN | 9.0 | 1.0 |
| 2022-06-06 | 4099.0 | 8.0 | 3.0 |
Part 3 : Data Analysis & Visualizations ¶
Time-Series of Attendance and Google Trends (f)¶
The following plots use the dataframes we created previously containting date-time, average weekly attendance, and google trends score to create a time series plot showing the relationship between attendance and google trends score.
As you can see, attendance only appears in blue during the season, whereas google trend scores in red and green appear year-round.
fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(14,6))
# Plot attendance on primary y-axis
# ax1 = fig.add_subplot(2,1,1)
ax[0].plot(fever_weekly_data.index, fever_weekly_data['Attendance'], color='blue', marker='o', label='Attendance')
ax[0].set_xlabel('Week')
ax[0].set_ylabel('Attendance', color='blue')
ax[0].tick_params(axis='y', labelcolor='blue')
ax[0].set_ylim(2500, 20000)
# Plot Google Trends on secondary y-axis
ax2 = ax[0].twinx()
ax2.plot(fever_weekly_data.index, fever_weekly_data['Indiana Fever'], color='red', marker='s', label='Indiana Fever Trends')
ax2.plot(fever_weekly_data.index, fever_weekly_data['Caitlin Clark'], color='green', marker='^', label='Caitlin Clark Trends')
ax2.set_ylabel('Google Trends Score', color='red')
ax2.tick_params(axis='y', labelcolor='red')
lines_1, labels_1 = ax[0].get_legend_handles_labels()
lines_2, labels_2 = ax2.get_legend_handles_labels()
ax[0].legend(lines_1 + lines_2, labels_1 + labels_2, loc='upper left')
# Title and layout
ax[0].set_title('Indiana Fever Attendance vs. Google Trends')
# Plot attendance on primary y-axis
# ax3 = fig.add_subplot(2,1,2)
ax[1].plot(liberty_weekly_data.index, liberty_weekly_data['Attendance'], color='blue', marker='o', label='Attendance')
ax[1].set_xlabel('Week')
ax[1].set_ylabel('Attendance', color='blue')
ax[1].tick_params(axis='y', labelcolor='blue')
ax[1].set_ylim(2500, 20000)
# Plot Google Trends on secondary y-axis
ax4 = ax[1].twinx()
ax4.plot(liberty_weekly_data.index, liberty_weekly_data['New York Liberty'], color='red', marker='s', label='New York Liberty Trends')
ax4.plot(liberty_weekly_data.index, liberty_weekly_data['Sabrina Ionescu'], color='green', marker='^', label='Sabrina Ionescu Trends')
ax4.set_ylabel('Google Trends Score', color='red')
ax4.tick_params(axis='y', labelcolor='red')
lines_1, labels_1 = ax[1].get_legend_handles_labels()
lines_2, labels_2 = ax4.get_legend_handles_labels()
ax[1].legend(lines_1 + lines_2, labels_1 + labels_2, loc='upper left')
# Title and layout
ax[1].set_title('New York Liberty Attendance vs. Google Trends')
fig.tight_layout()
plt.show()
This plot is signifigant for a few reasons, but it is important to note a few important things: Caitlin was drafted into the WNBA for the 2024 season, and Sabrina Ionescu was drafted into the WNBA for the 2020 season ; the WNBA is growing in popularity, so it is expected that with or without a star player, the game attendance will rise over time.
However, the spike we see when Caitlin enters the league in 2024 is incredible compared to New Yorks steady increase in attendance. You can clearly see how the social media spikes with Caitlin and the Fever as a search also induces a massive spike in attendance to Indiana Fever home games. While social media may not be the "reason" people are going to games- it certainly implies that people were more excited to attend games when Caitlin Arrived.
Linear Regression (a)¶
In the following code we try to create a linear regression model for Attendance and google trends scores for "Caitlin Clark"
# Scatter plot with linear regression
x1 = fever_weekly_data['Caitlin Clark']
y1 = fever_weekly_data['Attendance']
# Linear regression
slope1, intercept1, r_value1, p_value1, std_err1 = stats.linregress(x1, y1)
line1 = slope1 * x1 + intercept1
print(f"Pearson correlation (r): {r_value1:.3f}")
print(f"P-value: {p_value1:.3g}")
Pearson correlation (r): nan P-value: nan
Try for 2024-2025 only (too many 0 entries for google trends)
# Filter for 2024–2025 only
df1 = fever_weekly_data[(fever_weekly_data.index.year >= 2024) & (fever_weekly_data.index.year <= 2025)].copy()
# Remove missing or non-numeric values
df1 = df1[['Caitlin Clark', 'Attendance', 'Indiana Fever']].dropna()
# linear regression
x2 = df1['Caitlin Clark'].values
y2 = df1['Attendance'].values
slope2, intercept2, r_value2, p_value2, std_err2 = stats.linregress(x2, y2)
# Sort and predict for plotting
order2 = np.argsort(x2)
x_sorted2 = x2[order2]
y_pred2 = slope2 * x_sorted2 + intercept2
print(f"Pearson correlation (r): {r_value2:.3f}")
print(f"P-value: {p_value2:.3g}")
Pearson correlation (r): 0.264 P-value: 0.166
Now we try a regression with "Indiana Fever" as the google trends search:
# Scatter plot with linear regression
x3 = fever_weekly_data['Indiana Fever']
y3 = fever_weekly_data['Attendance']
# Linear regression
slope3, intercept3, r_value3, p_value3, std_err3 = stats.linregress(x3, y3)
line3 = slope3 * x3 + intercept3
print(f"Pearson correlation (r): {r_value3:.3f}")
print(f"P-value: {p_value3:.3g}")
Pearson correlation (r): nan P-value: nan
Again, too many 0 entries and no correlation so try with 2024-2025:
# Remove missing or non-numeric values
df1 = df1[['Indiana Fever', 'Attendance']].dropna()
# linear regression
x4 = df1['Indiana Fever'].values
y4 = df1['Attendance'].values
slope4, intercept4, r_value4, p_value4, std_err4 = stats.linregress(x4, y4)
# Sort and predict for plotting
order4 = np.argsort(x4)
x_sorted4 = x4[order4]
y_pred4 = slope4 * x_sorted4 + intercept4
print(f"Pearson correlation (r): {r_value4:.3f}")
print(f"P-value: {p_value4:.3g}")
Pearson correlation (r): 0.559 P-value: 0.00162
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
# plotting 2022-2025 data
ax[0,0].scatter(x1, y1, color='blue', label='Data points (2022-2025')
ax[0,0].plot(x1, line1, color='red', label=f'Linear fit (r={r_value1:.2f})')
ax[0,0].set_xlabel('Google Trends Score')
ax[0,0].set_ylabel('Weekly Attendance')
ax[0,0].set_title('Fever Attendance vs. "CC" Google Trends Scatter Plot')
ax[0,0].legend()
ax[0,1].scatter(x3, y3, color='blue', label='Data points (2022-2025')
ax[0,1].plot(x3, line3, color='red', label=f'Linear fit (r={r_value3:.2f})')
ax[0,1].set_xlabel('Google Trends Score')
ax[0,1].set_ylabel('Weekly Attendance')
ax[0,1].set_title('Fever Attendance vs. "Fever" Google Trends Scatter Plot')
ax[0,1].legend()
ax[1,0].scatter(x2, y2, color='blue', alpha=0.7, label='Data points (2024–2025)')
ax[1,0].plot(x_sorted2, y_pred2, color='red', label=f'Linear fit (r={r_value2:.2f}, p={p_value2:.3g})')
ax[1,0].set_xlabel('Google Trends Score')
ax[1,0].set_ylabel('Weekly Attendance')
ax[1,0].set_title('Fever Attendance vs. "CC" Google Trends (2024–2025)')
ax[1,0].legend()
ax[1,0].set_ylim(15000, 18000)
ax[1,1].scatter(x4, y4, color='blue', alpha=0.7, label='Data points (2024–2025)')
ax[1,1].plot(x_sorted4, y_pred4, color='red', label=f'Linear fit (r={r_value4:.2f}, p={p_value4:.3g})')
ax[1,1].set_xlabel('Google Trends Score')
ax[1,1].set_ylabel('Weekly Attendance')
ax[1,1].set_title('Fever Attendance vs. "Fever"" Google Trends (2024–2025)')
ax[1,1].legend()
ax[1,1].set_ylim(15000, 18000)
plt.tight_layout()
plt.show()
# for later plotting
caitlin_df = fever_weekly_data.copy()
The first row shows the linear regression models for both "Caitlin Clark" and "Indiana Fever" google trends from 2022-2025. There is no correlation likely due to the large ammount of trends scores and attendances that are 0.
When we look at just 2024-2025 to try and reduce the ammount of 0 entries, we see a slight correlation, but it is hard to draw any conclusions from these regression lines.
Below we follow the same framework to greate models for Ionescu and Liberty google trends scores to predict attendance.
# Scatter plot with linear regression
x1 = liberty_weekly_data['Sabrina Ionescu']
y1 = liberty_weekly_data['Attendance']
# Linear regression
slope1, intercept1, r_value1, p_value1, std_err1 = stats.linregress(x1, y1)
line1 = slope1 * x1 + intercept1
print(f"Pearson correlation (r): {r_value1:.3f}")
print(f"P-value: {p_value1:.3g}")
Pearson correlation (r): nan P-value: nan
#Filter for 2024–2025 only
df2 = liberty_weekly_data[(liberty_weekly_data.index.year >= 2024) & (liberty_weekly_data.index.year <= 2025)].copy()
# Remove missing or non-numeric values
df2 = df2[['Sabrina Ionescu', 'Attendance', 'New York Liberty']].dropna()
# linear regression
x2 = df2['Sabrina Ionescu'].values
y2 = df2['Attendance'].values
slope2, intercept2, r_value2, p_value2, std_err2 = stats.linregress(x2, y2)
# Sort and predict for plotting
order2 = np.argsort(x2)
x_sorted2 = x2[order2]
y_pred2 = slope2 * x_sorted2 + intercept2
print(f"Pearson correlation (r): {r_value2:.3f}")
print(f"P-value: {p_value2:.3g}")
Pearson correlation (r): 0.099 P-value: 0.602
# Scatter plot with linear regression
x3 = liberty_weekly_data['New York Liberty']
y3 = liberty_weekly_data['Attendance']
# Linear regression
slope3, intercept3, r_value3, p_value3, std_err3 = stats.linregress(x3, y3)
line3 = slope3 * x3 + intercept3
print(f"Pearson correlation (r): {r_value3:.3f}")
print(f"P-value: {p_value3:.3g}")
Pearson correlation (r): nan P-value: nan
# Remove missing or non-numeric values
df2 = df2[['New York Liberty', 'Attendance']].dropna()
# linear regression
x4 = df2['New York Liberty'].values
y4 = df2['Attendance'].values
slope4, intercept4, r_value4, p_value4, std_err4 = stats.linregress(x4, y4)
# Sort and predict for plotting
order4 = np.argsort(x4)
x_sorted4 = x4[order4]
y_pred4 = slope4 * x_sorted4 + intercept4
print(f"Pearson correlation (r): {r_value4:.3f}")
print(f"P-value: {p_value4:.3g}")
Pearson correlation (r): 0.174 P-value: 0.357
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
# plotting 2022-2025 data
ax[0,0].scatter(x1, y1, color='blue', label='Data points (2022-2025')
ax[0,0].plot(x1, line1, color='red', label=f'Linear fit (r={r_value1:.2f})')
ax[0,0].set_xlabel('Google Trends Score')
ax[0,0].set_ylabel('Weekly Attendance')
ax[0,0].set_title('Liberty Attendance vs. "SI" Google Trends Scatter Plot')
ax[0,0].legend()
ax[0,1].scatter(x3, y3, color='blue', label='Data points (2022-2025')
ax[0,1].plot(x3, line3, color='red', label=f'Linear fit (r={r_value3:.2f})')
ax[0,1].set_xlabel('Google Trends Score')
ax[0,1].set_ylabel('Weekly Attendance')
ax[0,1].set_title('Liberty Attendance vs. "Liberty" Google Trends Scatter Plot')
ax[0,1].legend()
ax[1,0].scatter(x2, y2, color='blue', alpha=0.7, label='Data points (2024–2025)')
ax[1,0].plot(x_sorted2, y_pred2, color='red', label=f'Linear fit (r={r_value2:.2f}, p={p_value2:.3g})')
ax[1,0].set_xlabel('Google Trends Score')
ax[1,0].set_ylabel('Weekly Attendance')
ax[1,0].set_title('Liberty Attendance vs. "SI" Google Trends (2024–2025)')
ax[1,0].legend()
ax[1,1].scatter(x4, y4, color='blue', alpha=0.7, label='Data points (2024–2025)')
ax[1,1].plot(x_sorted4, y_pred4, color='red', label=f'Linear fit (r={r_value4:.2f}, p={p_value4:.3g})')
ax[1,1].set_xlabel('Google Trends Score')
ax[1,1].set_ylabel('Weekly Attendance')
ax[1,1].set_title('Liberty Attendance vs. "Liberty" Google Trends (2024–2025)')
ax[1,1].legend()
plt.tight_layout()
plt.show()
# for later plotting
caitlin_df = fever_weekly_data.copy()
Same as the graphs representing Fever and Clark, these graphs also do not show strong correlations between gogle trends scores and attendance.
Although it may be useful to examine these regression models to see some correlation, it may make more sense to use different predictors for a regression model.
After analyzing google trends data we decided google trends scores alone were not a great predictor for attendance.
Empirical Probability Distribution (f)¶
Below we create a dataframe that contains only regular season games when Indiana played as either the home or away team alongside attendance.
We then decided to observe attendance rates before and after Clark joined the league, defined as preCC (before 2024) and postCC (2024-25).
These Empiracle Probability Distributions show a very interesting correlation between attendance and Clark joining the league seen below:
# Set up and filter out postseason games
ind = df[
((df['Home Team'] == 'Indiana Fever') |
(df['Away Team'] == 'Indiana Fever')) &
(df['Game Type'] == 'Regular season')]
## note that when ind is defined as
# ind = df[
# (df['Home Team'] == 'Indiana Fever') &
# (df['Game Type'] == 'Regular season')]
# charts look drastically different, it's clear that the lower attendance games were at away games,
# with teams that don't have as high of an average attendance
## Split between eras of games before Caitlin Clark and after
ipreCC = ind[ind['Year'].between(2021,2023)]
ipostCC = ind[ind['Year'].between(2024,2025)]
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15, 5))
ax[0].hist(ind['Attendance'], bins=20, density=True)
ax[0].set_title("Empirical Probability Distribution of IN Fever Attendance (2021–2025)")
ax[0].set_xlabel("Attendance")
ax[0].set_ylabel("Probability Density")
ax[1].hist(ipreCC['Attendance'], bins=20, density=True, alpha=0.6, label="2021–2023 (Pre-CC)")
ax[1].hist(ipostCC['Attendance'], bins=20, density=True, alpha=0.6, label="2024–2025 (Post-CC)")
ax[1].set_title("IN Fever Attendance Distribution: Pre vs Post Caitlin Clark Era")
ax[1].set_xlabel("Attendance")
ax[1].set_ylabel("Probability Density")
ax[1].legend()
plt.show()
print((ipreCC['Attendance']).mean())
print((ipostCC['Attendance']).mean())
4624.3026315789475 16156.261904761905
In these distributions we can see two sort of "groups". One grouped at the lower attendance in the pre-CC era with a mean of 4192, and one at higher attendance in the post-CC era with a mean of 16156. This difference in attendances may also take into account that CC came into the leage when attendance numbers started to rise due to covid attendance bans, but also beacuse of the traction that CC had throughout the league. It is undeniable that CC had an impact on attendance over time.
As you can see there is a large spike in the distribution around 17500, this is because indiana fever home games have a max attendacne of around 17,500, so we can see that there is more games with that attendance because of all of the home games that were at max capacity in the post-CC era.
We follow the same framework below to observe Liberty attendance rates before and after Clark.
# Set up and filter out postseason games
nyl = df[
((df['Home Team'] == 'New York Liberty') |
(df['Away Team'] == 'New York Liberty')) &
(df['Game Type'] == 'Regular season')]
## note that when nyl is defined as
# nyl = df[
# (df['Home Team'] == 'New York Liberty') &
# (df['Game Type'] == 'Regular season')]
# charts look drastically different, it's clear that the lower attendance games were at away games,
# with teams that don't have as high of an average attendance
## Split between eras of games before Caitlin Clark and after
lpreCC = nyl[nyl['Year'].between(2021,2023)]
lpostCC = nyl[nyl['Year'].between(2024,2025)]
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15, 5))
ax[0].hist(nyl['Attendance'], bins=20, density=True)
ax[0].set_title("Empirical Probability Distribution of NY Liberty Attendance (2021–2025)")
ax[0].set_xlabel("Attendance")
ax[0].set_ylabel("Probability Density")
ax[1].hist(lpreCC['Attendance'], bins=20, density=True, alpha=0.6, label="2021–2023 (Pre-CC)")
ax[1].hist(lpostCC['Attendance'], bins=20, density=True, alpha=0.6, label="2024–2025 (Post-CC)")
ax[1].set_title("NY Liberty Attendance Distribution: Pre vs Post Caitlin Clark Era")
ax[1].set_xlabel("Attendance")
ax[1].set_ylabel("Probability Density")
ax[1].legend()
plt.show()
print((lpreCC['Attendance']).mean())
print((lpostCC['Attendance']).mean())
6512.960526315789 12160.107142857143
In these distributions, we can see two sections, sorted in orange and blue. One grouped at the lower attendance in the pre-CC era with a mean of 6513, and a higher attendance value in the post-CC era with a mean of 12160. The difference is quite drastic; Caitlin Clark plays a role in this change but I also believe that there are other factors. In 2021, the league was dealing with the effects of COVID. All of 2020, attendance waas not allowed in games, so 2021 was low for attendance as fans were still adjusting to being back in person with everyone. However, Caitlin Clark's impact on NYL is less on NYL's stats alone and more on her overall impact on the WNBA. Sabrina Ionescu's rookie year was in 2020 unfortunately, but even in 2021 and 2022, her status on the court, despite having a shoe brand with Nike, goes unnoticed in this data field. It's interesting to show how Caitlin Clark can impact teams that aren't her own. More Clarity shown below to prove CC's impact.
Lastly, something important to note is the capacity rate of arenas. Each team plays at arenas with varying numbers for capacity, so that could explain the spike in numbers between 10,000 and 12,500, as the average capacity is about 13,400 across all arenas. ( https://sports.betmgm.com/en/blog/wnba/biggest-wnba-arenas-ranking-by-capacity-bm23/)
as you can see, the highest attended games preCC were scattered among teams including Phoenix Mercury and Las Vegas Aces. Even the highest attended game in the preCC era (11,724) doesn't come close to the number in the postCC era (18,064). Obviously a lot of these metrics also come down to arena capacity, which we hope to investigate in the future. But even glancing at the top ten games in the last two years, Indiana Fever makes up for 4/10 top 10 spots.
Looking at Attendance for Indiana vs Other Teams to Determine Impact (a)¶
Histograms of Attendance with/without Indiana (a)¶
Below we create two categories: one where Indaina is the opponent and one where indiana is not the opponent. This explration hopes to observe how the Fever have impacted the league as a whole rather than just the Indiana Fever.
# Create two categories:
# 1. Attendance for each team when Indiana Fever is the opponent
fever_games = df[df['Away Team'] == 'Indiana Fever']
# 2. Attendance for each team when Indiana Fever is NOT the opponent
other_games = df[df['Away Team'] != 'Indiana Fever']
# Calculate mean attendance for each team
mean_fever = fever_games.groupby('Home Team')['Attendance'].mean()
mean_other = other_games.groupby('Home Team')['Attendance'].mean()
# Create a df
attendance_compare = pd.DataFrame({
'With Indiana': mean_fever,
'Without Indiana': mean_other})
# Now try grouping attendance by Year
mean_fever_year = fever_games.groupby('Year')['Attendance'].mean()
mean_other_year = other_games.groupby('Year')['Attendance'].mean()
# create a df for groupped data
attendance_compare2 = pd.DataFrame({
'With Indiana': mean_fever_year,
'Without Indiana': mean_other_year})
# Replace NaN with 0 for teams that never played Indiana at home
attendance_compare2 = attendance_compare2.fillna(0)
fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(14,6))
# --- Graph of Team's Attendance With/Without Indiana ---
# get rid of unwanted teams
attendance_compare = attendance_compare.drop(
index=["Team WNBA", "Team Wilson", "Team Clark", "Indiana Fever"], errors="ignore")
teams = attendance_compare.index
x1 = np.arange(len(teams)) # the label locations
width1 = 0.35 # width of the bars
# ax1 = fig.add_subplot(2,1,1)
ax[0].bar(x1 - width1/2, attendance_compare['With Indiana'], width1, label='Playing Indiana')
ax[0].bar(x1 + width1/2, attendance_compare['Without Indiana'], width1, label='Not Playing Indiana')
ax[0].set_xlabel('Home Team')
ax[0].set_ylabel('Mean Attendance')
ax[0].set_title('Mean Attendance: Playing Indiana vs. Other Opponents')
ax[0].set_xticks(x1)
ax[0].set_xticklabels(teams, rotation=45)
ax[0].legend()
ax[0].set_ylim(0, 20000)
# --- Graph of Attendance Per Year With/Without Indiana ---
years = attendance_compare2.index
x2 = np.arange(len(years)) # the label locations
width2 = 0.35 # width of the bars
# ax2 = fig.add_subplot(2,1,2)
ax[1].bar(x2 - width2/2, attendance_compare2['With Indiana'], width2, label='Playing Indiana')
ax[1].bar(x2 + width2/2, attendance_compare2['Without Indiana'], width2, label='Not Playing Indiana')
ax[1].set_xlabel('Home Team')
ax[1].set_ylabel('Mean Attendance')
ax[1].set_title('Mean Attendance: Playing Indiana vs. Other Opponents')
ax[1].set_xticks(x2)
ax[1].set_xticklabels(years, rotation=45)
ax[1].legend()
ax[1].set_ylim(0, 20000)
plt.tight_layout()
plt.show()
These graphs are particlarly interesting because you can very clearly see how impactful Indiana is on opponents attendance. There is a visable difference between attendance when a team plays Indiana, and when we look at the difference over the course of the past 4 years, we can see that margin grow even larger. When Caitlin started playing at Indiana, other teams' attendance spiked when Indiana was on the road. This shows that people from all over are coming to support Indaina Fever and Caitlin Clark due to her impact on the WNBA and the sports world in general.
Below we follow the sae framework for the Liberty to see if this (very successful) team impacts the league like the Fever does.
# Create two categories:
# 1. Attendance for each team when New York Liberty is the opponent
liberty_games = df[df['Away Team'] == 'New York Liberty']
# 2. Attendance for each tea when NYL is NOT the opponent
notlib_games = df[df['Away Team'] != 'New York Liberty']
# Calculating mean attendance for each game category
mean_lib = liberty_games.groupby('Home Team')['Attendance'].mean()
mean_notlib = notlib_games.groupby('Home Team')['Attendance'].mean()
# Create a df
lib_attendance_compare = pd.DataFrame({
'With New York Liberty': mean_lib,
'Without New York Liberty': mean_notlib})
# Grouping attendance per Year
mean_lib_year = liberty_games.groupby('Year')['Attendance'].mean()
mean_notlib_year = notlib_games.groupby('Year')['Attendance'].mean()
# Create df for groupped data
lib_attendance_compare2 = pd.DataFrame({
'With New York Liberty': mean_lib_year,
'Without New York Liberty': mean_notlib_year})
# Replace NaN with 0 for teams that never played New York Liberty at home
lib_attendance_compare2 = lib_attendance_compare2.fillna(0)
fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(14,6))
# --- Graph of Team's Attendance With/Without NYL ---
# get rid of unwanted teams
lib_attendance_compare = lib_attendance_compare.drop(
index=["Team WNBA", "Team Wilson", "Team Clark", "New York Liberty"], errors="ignore")
teams = lib_attendance_compare.index
x1 = np.arange(len(teams)) # the label locations
width1 = 0.35 # width of the bars
ax[0].bar(x1 - width1/2, lib_attendance_compare['With New York Liberty'], width1, label='Playing NYL')
ax[0].bar(x1 + width1/2, lib_attendance_compare['Without New York Liberty'], width1, label='Not Playing NYL')
ax[0].set_xlabel('Home Team')
ax[0].set_ylabel('Mean Attendance')
ax[0].set_title('Mean Attendance: Playing New York Liberty vs. Other Opponents')
ax[0].set_xticks(x1)
ax[0].set_xticklabels(teams, rotation=45)
ax[0].legend()
ax[0].set_ylim(0, 20000)
# --- Graph of Attendance Per Year With/Without NYL ---
years = lib_attendance_compare2.index
x2 = np.arange(len(years)) # the label locations
width2 = 0.35 # width of the bars
ax[1].bar(x2 - width2/2, lib_attendance_compare2['With New York Liberty'], width2, label='Playing NYL')
ax[1].bar(x2 + width2/2, lib_attendance_compare2['Without New York Liberty'], width2, label='Not Playing NYL')
ax[1].set_xlabel('Home Team')
ax[1].set_ylabel('Mean Attendance')
ax[1].set_title('Mean Attendance: Playing NYL vs. Other Opponents')
ax[1].set_xticks(x2)
ax[1].set_xticklabels(years, rotation=45)
ax[1].legend()
ax[1].set_ylim(0, 20000)
plt.tight_layout()
plt.show()
As time passes, it's nice to see that the league has gotten more popular (for both Fever and Liberty) during these 2024 and 2025 seasons. This increase in popularity does not appear to be due to the New York Liberty, according to the ticket sales alone. Golden State Valkyries data can be ignored since they basically sold out every single game in their inaugural season during 2025. But considering the others, it looks like NYL usually has an increased attendance while playing others but not everytime. While this is still impressive, it's not nearly as drastic as the attendance Fever gets when they play at home and away.
Linear Regression of Attendance (a)¶
fever_means_list = mean_fever_year.tolist()
other_means_list = mean_other_year.tolist()
# data
x = np.array([2022, 2023, 2024, 2025])
y1 = np.array(fever_means_list) # mean attendance when playing Indiana
y2 = np.array(other_means_list) # mean attendance when not playing Indiana
# linear regression for each
slope1, intercept1, r_value1, p_value1, std_err1 = stats.linregress(x, y1)
slope2, intercept2, r_value2, p_value2, std_err2 = stats.linregress(x, y2)
line1 = slope1 * x + intercept1
line2 = slope2 * x + intercept2
# Plot
plt.figure(figsize=(6,4))
plt.scatter(x, y1, color='blue', label='Playing Indiana')
plt.plot(x, line1, color='blue', linestyle='--', label=f'Indiana Fit (r={r_value1:.2f})')
plt.scatter(x, y2, color='orange', label='Not Playing Indiana')
plt.plot(x, line2, color='orange', linestyle='--', label=f'Other Fit (r={r_value2:.2f})')
plt.xlabel('Season (Year)')
plt.ylabel('Mean Attendance')
plt.title('Mean Attendance Trend by Season')
plt.legend()
plt.tight_layout()
plt.show()
We expect the orange line to look like that because the attendance of the WNBA is growing gover time, but in the blue line we see the massive jump in attendance when Indiana is playing in a game, likely due to Caitlin's introduction into the league in 2024. It almost takes an exponential jump from 2023-24 and I expect the line to increase linearly from 2023 forward. This does show just how impactful Caitlin coming into the league was on attendance to WNBA basketball games, particularly ones involving the Indiana Fever.
Average Attendance Rates Across the League (f)¶
We wanted to create visualizations that take more than just the mean attendance, since a lot of arenas have varying attendance capacities. For instance, Atlanta Dream's seat capacity is 3500, while the Fever arena's capacity is around 17,000. At this point, the Atlanta Dream's attendance games could be considered outliers for calculating mean attendances.
In order to acknowledge these diverse ranges for seat capacities, we manually developed a .csv file that stored all seat capacities for every arena used in the last 5 years. We then added columns for showing Seat Capacity and Attendance rate for every game.
## Finding the arenas that I need to find the capacities of
df = pd.read_csv('Attendance_2021-2025_WithSeats.csv')
df = df.rename(columns=lambda c: c.replace(" ", "_"))
q = """
SELECT DISTINCT Home_Team, Arena
FROM df
where Game_Type = 'Regular season'
order by Home_Team ASC
"""
sqldf(q)
| Home_Team | Arena | |
|---|---|---|
| 0 | Atlanta Dream | Gateway Center Arena @ College Park |
| 1 | Atlanta Dream | State Farm Arena |
| 2 | Atlanta Dream | Rogers Arena |
| 3 | Chicago Sky | Wintrust Arena |
| 4 | Chicago Sky | United Center |
| 5 | Connecticut Sun | Mohegan Sun Arena |
| 6 | Connecticut Sun | TD Garden |
| 7 | Dallas Wings | College Park Center |
| 8 | Dallas Wings | American Airlines Center |
| 9 | Golden State Valkyries | Chase Center |
| 10 | Indiana Fever | Gainbridge Fieldhouse |
| 11 | Indiana Fever | Indiana Farmers Coliseum |
| 12 | Indiana Fever | Hinkle Fieldhouse |
| 13 | Las Vegas Aces | Michelob ULTRA Arena |
| 14 | Las Vegas Aces | T-Mobile Arena |
| 15 | Los Angeles Sparks | Los Angeles Convention Center |
| 16 | Los Angeles Sparks | STAPLES Center |
| 17 | Los Angeles Sparks | Crypto.com Arena |
| 18 | Los Angeles Sparks | Galen Center |
| 19 | Los Angeles Sparks | Walter Pyramid at Long Beach State |
| 20 | Minnesota Lynx | Target Center |
| 21 | New York Liberty | Barclays Center |
| 22 | Phoenix Mercury | Phoenix Suns Arena |
| 23 | Phoenix Mercury | Footprint Center |
| 24 | Phoenix Mercury | PHX Arena |
| 25 | Seattle Storm | Angel of the Winds Arena |
| 26 | Seattle Storm | Climate Pledge Arena |
| 27 | Washington Mystics | Entertainment and Sports Arena |
| 28 | Washington Mystics | Capital One Arena |
| 29 | Washington Mystics | CareFirst Arena |
| 30 | Washington Mystics | CFG Bank Arena |
| 31 | Washington Mystics | EagleBank Arena |
## HAVE TO CHANGE SO THERE IS A ATTENDANCERATE COLUMN
# Load your CSV
df = pd.read_csv('Attendance_2021-2025_WithSeats.csv')
# Create the new column
df['AttendanceRate'] = df['Attendance'] / df['SeatCapacity']
# Optionally, round to 2 decimal places
df['AttendanceRate'] = df['AttendanceRate'].round(2)
# Save back to a new CSV
df.to_csv('Attendance_2021-2025_WithSeats_Rates.csv', index=False)
df.head()
| Year | Day_of_Week | Month | Day | Time_(ET) | Game_Type | Home_Team | Away_Team | Arena | City | State | Attendance | SeatCapacity | Date | SeatCapacity.1 | AttendanceRate | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2021 | Friday | May | 14 | 7:00 PM | Regular season | New York Liberty | Indiana Fever | Barclays Center | Brooklyn | NY | 1139 | 19000.0 | 2021-05-14 | 19000.0 | 0.06 |
| 1 | 2021 | Friday | May | 14 | 3:00 AM | Regular season | Atlanta Dream | Connecticut Sun | Gateway Center Arena @ College Park | Atlanta | GA | 561 | 3500.0 | 2021-05-14 | 3500.0 | 0.16 |
| 2 | 2021 | Friday | May | 14 | 9:00 PM | Regular season | Minnesota Lynx | Phoenix Mercury | Target Center | Minneapolis | MN | 2021 | 20500.0 | 2021-05-14 | 20500.0 | 0.10 |
| 3 | 2021 | Saturday | May | 15 | 1:00 PM | Regular season | Washington Mystics | Chicago Sky | Entertainment and Sports Arena | Washington | DC | 1050 | 4200.0 | 2021-05-15 | 4200.0 | 0.25 |
| 4 | 2021 | Saturday | May | 15 | 3:00 PM | Regular season | Seattle Storm | Las Vegas Aces | Angel of the Winds Arena | Everett | WA | 1031 | 10000.0 | 2021-05-15 | 10000.0 | 0.10 |
## SHOWING AVERAGE ATTENDANCE RATE FOR WNBA TEAMS THROUGHOUT THE YEARS
df = pd.read_csv('Attendance_2021-2025_WithSeats_Rates.csv')
# Use home team as the team identifier
df['AttendanceRate'] = pd.to_numeric(df['AttendanceRate'], errors='coerce')
df['Year'] = pd.to_numeric(df['Year'], errors='coerce')
wnba_teams = [
'Atlanta Dream',
'Chicago Sky',
'Connecticut Sun',
'Dallas Wings',
'Indiana Fever',
'Las Vegas Aces',
'Los Angeles Sparks',
'Minnesota Lynx',
'New York Liberty',
'Phoenix Mercury',
'Seattle Storm',
'Washington Mystics'
]
# Keep only real WNBA teams
df = df[df['Home_Team'].isin(wnba_teams)]
avg_df = df.groupby(['Home_Team', 'Year'])['AttendanceRate'].mean().reset_index()
# WNBA team branding colors
team_colors = {
'Atlanta Dream': '#E03A3E',
'Chicago Sky': '#FDBB30',
'Connecticut Sun': '#F47932',
'Dallas Wings': '#0072CE',
'Indiana Fever': '#BA0C2F',
'Las Vegas Aces': '#000000',
'Los Angeles Sparks': '#552583',
'Minnesota Lynx': '#236192',
'New York Liberty': '#00A3A0',
'Phoenix Mercury': '#1D1160',
'Seattle Storm': '#2C5234',
'Washington Mystics': '#002B5C'
}
plt.figure(figsize=(12, 8))
for team in avg_df['Home_Team'].unique():
team_data = avg_df[avg_df['Home_Team'] == team]
plt.plot(
team_data['Year'],
team_data['AttendanceRate'],
marker='o',
linewidth=2,
label=team,
color=team_colors.get(team, None)
)
plt.title('Average Attendance Rate per Season (2021–2025)')
plt.xlabel('Season')
plt.ylabel('Average Attendance Rate')
plt.xticks([2021, 2022, 2023, 2024, 2025])
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
We created a visualization to demonstrate the change in attendance rates per team throughout the years. 2021 showed record low numbers, with no team's attendance rate being higher than 50%. However, this is due to COVID bans still in the process of being lifted; this explains the great increase from 2021 and 2022. The other significant increase happens between the 2023 and 2024 seasons. Every single team's attendance rate increased, some teams as little as 4% of an increase , other teams as high as 72%. Indiana Fever's attendance rate increased 72% during this period, which is likely due to Caitlin's involvement on the team. This is also interesting because even though Aliyah Boston was also the #1 draft pick selected by the Fever in 2023, but her involvement in the team's attendance rate did not increase much, especially in comparison to the next season. Overall, the average increase of attendance rates between 2023 and 2024 is ~20%.
# Filter only 2023 and 2024
subset = avg_df[avg_df['Year'].isin([2023, 2024])]
# Pivot so each team has a column for each year
pivot = subset.pivot(index='Home_Team', columns='Year', values='AttendanceRate')
# Compute the change from 2023 to 2024
pivot['Increase_23_to_24'] = pivot[2024] - pivot[2023]
print("Attendance Rate Increase from 2023 to 2024 by Team:")
print(pivot['Increase_23_to_24'])
# Compute league-wide average increase
avg_increase = pivot['Increase_23_to_24'].mean()
print("\nAverage Increase Across All Teams:")
print(avg_increase)
Attendance Rate Increase from 2023 to 2024 by Team: Home_Team Atlanta Dream 0.095500 Chicago Sky 0.147500 Connecticut Sun 0.165000 Dallas Wings 0.167478 Indiana Fever 0.721000 Las Vegas Aces 0.103974 Los Angeles Sparks 0.292500 Minnesota Lynx 0.102434 New York Liberty 0.241496 Phoenix Mercury 0.090000 Seattle Storm 0.122000 Washington Mystics 0.048000 Name: Increase_23_to_24, dtype: float64 Average Increase Across All Teams: 0.1914068507311261
Binary Classification and AUC of ROC (a)¶
0 = Indiana Fever not playing
1 = Indiana Fever playing
Below we create a binary classification depending on weather or not the Fever is playing.
Will our logistic model be able to accurately predict weather or not the Fever is playing based off of just attendance?
Throughout this project we have seen that Clark and the Fever bring in huge attendace numebers weather they are at home or not. This Binary Classification and AUC hopes to explore that.
After careful observation we observed some outliers so we decided to remove one of the highest attended teams: Golden State. They were just introduced into the league in 2025 and showcase WNBA stars from all over the league. This new team has gained a lot of traction due to their success and we decided it may cause some noise in our data.
df = pd.read_csv('Attendance_2022-2025.csv')
CC_era = df[df['Year'] >= 2024].copy()
CC_era['Indiana_Playing'] = (
(CC_era['Home Team'] == 'Indiana Fever') |
(CC_era['Away Team'] == 'Indiana Fever')
).astype(int)
threshold = CC_era['Attendance'].mean()
CC_era['Binary_Attendance'] = CC_era['Attendance'].apply(lambda x: 1 if x >= threshold else 0)
Here we create a new df without Golden State.
CC_era_no_gs = df[df['Year'] >= 2024].copy()
CC_era_no_gs = CC_era_no_gs[
(CC_era_no_gs['Home Team'] != 'Golden State Valkyries') &
(CC_era_no_gs['Away Team'] != 'Golden State Valkyries')
]
CC_era_no_gs['Indiana_Playing'] = (
(CC_era_no_gs['Home Team'] == 'Indiana Fever') |
(CC_era_no_gs['Away Team'] == 'Indiana Fever')
).astype(int)
threshold = CC_era_no_gs['Attendance'].mean()
CC_era_no_gs['Binary_Attendance'] = CC_era_no_gs['Attendance'].apply(lambda x: 1 if x >= threshold else 0)
Define 2 x and y variabels, one with GS and one without.
X1 = CC_era[['Attendance']]
y1 = CC_era['Indiana_Playing']
X2 = CC_era_no_gs[['Attendance']]
y2 = CC_era_no_gs['Indiana_Playing']
Here we train our model and prform a logistic regression on the data. We get predicted probabilities and compute AUC.
# Training fractions
fractions = np.linspace(0.1, 0.9, 9)
aucs = []
both = [[X1, y1], [X2, y2]]
for i in both:
X = i[0]
y = i[1]
print("\n")
print("TRAIN SIZE | AUC | MODEL COEFFICIENTS")
print("---------------------------------------")
for frac in fractions:
# train/test split
X_train, X_test, y_train, y_test = train_test_split(
X, y, train_size=frac, random_state=42
)
# train logistic regression
model = LogisticRegression()
model.fit(X_train, y_train)
# get predicted probabilities
y_prob = model.predict_proba(X_test)[:, 1]
# compute AUC
auc = roc_auc_score(y_test, y_prob)
aucs.append(auc)
# print model and AUC
print(f"{frac:.1f} | {auc:.4f} | Coef: {model.coef_}")
TRAIN SIZE | AUC | MODEL COEFFICIENTS --------------------------------------- 0.1 | 0.8487 | Coef: [[0.00018023]] 0.2 | 0.8495 | Coef: [[0.00030343]] 0.3 | 0.8433 | Coef: [[0.00034978]] 0.4 | 0.8372 | Coef: [[0.00035557]] 0.5 | 0.8624 | Coef: [[0.00032044]] 0.6 | 0.8425 | Coef: [[0.00034564]] 0.7 | 0.7894 | Coef: [[0.00037694]] 0.8 | 0.7477 | Coef: [[0.00038791]] 0.9 | 0.7462 | Coef: [[0.00035782]] TRAIN SIZE | AUC | MODEL COEFFICIENTS --------------------------------------- 0.1 | 0.8678 | Coef: [[0.00042058]] 0.2 | 0.8712 | Coef: [[0.00035937]] 0.3 | 0.8606 | Coef: [[0.00044449]] 0.4 | 0.8599 | Coef: [[0.0004411]] 0.5 | 0.8559 | Coef: [[0.0004468]] 0.6 | 0.8707 | Coef: [[0.00041185]] 0.7 | 0.8497 | Coef: [[0.00042217]] 0.8 | 0.8736 | Coef: [[0.00039494]] 0.9 | 0.8979 | Coef: [[0.00039576]]
Plotting our AUC vs training size.
# Plot AUC vs training size
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(14,6))
ax[0].plot(fractions, aucs[0:9], marker='o')
ax[0].set_xlabel("Training Size (α)")
ax[0].set_ylabel("AUC")
ax[0].set_title("AUC vs Training Size\nPredicting Indiana Fever Games from Attendance")
ax[0].grid(True)
ax[0].set_ylim(0.7, 0.9)
ax[1].plot(fractions, aucs[9:], marker='o')
ax[1].set_xlabel("Training Size (α)")
ax[1].set_ylabel("AUC")
ax[1].set_title("AUC vs Training Size\nPredicting Indiana Fever Games from Attendance (no gs)")
ax[1].grid(True)
ax[1].set_ylim(0.7, 0.9)
plt.show()
In the left graph with GS, we see that there is a higher accuracy when traiing size sits aroun 0.5, meaning as we introduce more training data, it gets more noisy and harder to accurately predict weather or not indiana is playing.
In the right graph not contaiing GS our accuracy increases as training size gets larger, meaning that removing GS eleviates any super high attendace scores that could interrupt our prediction accuracy.
the fact that our model can accurately predict weather or not the Fever is playing based solely off of attendance scores shows that the fever have anything but average attendance rates.
Part 4 : Interpretation and Conclusions ¶
We began this project hoping to explore the relationship between Google Trends data for Caitlin Clark and WNBA attendance, aiming to observe her influence on the league. While we found that Google Trends alone may not be the most reliable predictor of attendance, our analysis did reveal a clear correlation between spikes in Clark’s social media traction and increases in both Indiana Fever and overall league attendance. This demonstrates that even casual observers can recognize the substantial impact Caitlin Clark has had on the Fever and the WNBA as a whole. Her personal brand is extraordinary, and she has reshaped the league’s visibility and appeal, making games more engaging for fans across all demographics. Clark’s rise to household-name status, built on her remarkable collegiate career, has carried seamlessly into the WNBA.
Examining attendance trends over the years further highlights her influence, with noticeable increases following her entry into the league. It is exciting to witness teams like the Golden State Valkyries gain traction, attracting fans from both traditional audiences and new viewers. This growing support is a direct result of trailblazing players like Caitlin Clark, who have elevated the league, demonstrated the excitement of women’s basketball, and set the stage for future stars. In doing so, they show that the WNBA can captivate audiences just as dramatically as the NBA, offering high-level talent, memorable moments, and a vibrant fan experience. The WNBA is stronger, more visible, and more exciting because of her—and the future looks brighter than ever.