PRACTICAL 5: EXPLORATORY DATA ANALYSIS (EDA)

STEPS:
1. Install the libraries:  pip install pandas numpy seaborn matplotlib
2. Load Match.csv.
3. For every numeric column find mean, median, mode, skewness and kurtosis and tell the type of skew.
4. Plot the venue-wise wins of the teams at the top 10 venues (bar plot).
5. Plot the toss decision frequency (bar plot).
6. Map the team ids to team names and plot the home ground wins (pie chart).
7. Plot the venue-wise wins (scatter plot), winning margin by toss decision (box plot and violin plot).
8. Plot the frequency of win types (line plot) and winner by toss decision (swarm plot).
9. Plot the home wins as a donut chart and venue, toss decision and win type as a 3D scatter plot.

CODE:
from math import isclose
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
df=pd.read_csv("Match.csv")
num_cols=df.select_dtypes(include=[np.number]).columns
for col in num_cols:
  mean_val=df[col].mean()
  meadian_val=df[col].median()
  mode_val=df[col].mode().iloc[0]
  skew_val=df[col].skew()
  kurtosis_val=df[col].kurtosis()
  print(f"Mean of {col}: {mean_val}")
  print(f"Median of {col}: {meadian_val}")
  print(f"Mode of {col}: {mode_val}")
  print(f"Skewness of {col}: {skew_val}")
  print(f"Kurtosis of {col}: {kurtosis_val}")
  print("\n")
  if np.isclose(skew_val,0,atol=0.1):
    print("Data is symmetric")
  elif skew_val>0:
    print("Data is positively skewed")
  else:
    print("Data is negatively skewed")
  print("-"*70)
venue_wins = (
    df.groupby(['Venue_Name', 'Match_Winner_Id'])
      .size()
      .reset_index(name='Wins')
)
# Select top 10 venues by number of matches
top_venues = df['Venue_Name'].value_counts().head(10).index
venue_wins = venue_wins[venue_wins['Venue_Name'].isin(top_venues)]
plt.figure(figsize=(14,7))
sns.barplot(
    data=venue_wins,
    x='Venue_Name',
    y='Wins',
    hue='Match_Winner_Id'
)
plt.xticks(rotation=45, ha='right')
plt.title('Venue Advantage: Wins by Team at Top Venues')
plt.xlabel('Venue')
plt.ylabel('Number of Wins')
plt.tight_layout()
plt.show()
toss_counts = df['Toss_Decision'].value_counts()
toss_counts.plot(
    kind='bar',
    color=['skyblue', 'orange'],
    figsize=(6,5)
)
plt.title('Frequency of Toss Decisions')
plt.xlabel('Toss Decision')
plt.ylabel('Number of Matches')
for i, v in enumerate(toss_counts):
    plt.text(i, v + 2, str(v), ha='center')
plt.show()
team_id_name_pairs = pd.concat([
    df[['Opponent_Team_Id', 'Team name']].rename(columns={'Opponent_Team_Id': 'Team_ID', 'Team name': 'Team_Name'}),
    df[['Opponent_Team_Id', 'OpponentTeam name']].rename(columns={'Opponent_Team_Id': 'Team_ID', 'OpponentTeam name': 'Team_Name'}),
    df[['Match_Winner_Id', 'Team name']].rename(columns={'Match_Winner_Id': 'Team_ID', 'Team name': 'Team_Name'}),
    df[['Match_Winner_Id', 'OpponentTeam name']].rename(columns={'Match_Winner_Id': 'Team_ID', 'OpponentTeam name': 'Team_Name'})
]).drop_duplicates().dropna(subset=['Team_ID', 'Team_Name'])
team_map = team_id_name_pairs.groupby('Team_ID')['Team_Name'].first()
# Add winner name column
df['Match_Winner_Id'] = df['Match_Winner_Id'].map(team_map)
# Home wins
home_wins = df[df['OpponentTeam name'] == df['Match_Winner_Id']]
home_win_counts = home_wins['OpponentTeam name'].value_counts()
plt.figure(figsize=(8,8))
plt.pie(
    home_win_counts,
    labels=home_win_counts.index,
    autopct='%1.1f%%',
    startangle=90
)
plt.title('Home Ground Wins by Team')
plt.axis('equal')
plt.show()
venue_wins = (
    df.groupby(['Venue_Name', 'Match_Winner_Id'])
      .size()
      .reset_index(name='Wins')
)
# Top 10 venues
top_venues = df['Venue_Name'].value_counts().head(10).index
venue_wins = venue_wins[venue_wins['Venue_Name'].isin(top_venues)]
# Convert venue names to numeric positions
venue_positions = {venue: i for i, venue in enumerate(top_venues)}
venue_wins['Venue_Pos'] = venue_wins['Venue_Name'].map(venue_positions)
# Convert 'Match_Winner_Id' (team names) to numerical categories for plotting
venue_wins['Team_Numeric_ID'], unique_teams = pd.factorize(venue_wins['Match_Winner_Id'])
# Scatter Plot
plt.figure(figsize=(14,7))
scatter = plt.scatter(
    venue_wins['Venue_Pos'],
    venue_wins['Wins'],
    s=120,
    c=venue_wins['Team_Numeric_ID'], # Use numerical IDs for coloring
    cmap='tab20',
    alpha=0.8
)
plt.xticks(
    range(len(top_venues)),
    top_venues,
    rotation=45,
    ha='right'
)
plt.xlabel('Venue')
plt.ylabel('Number of Wins')
plt.title('Venue-wise Wins by Teams (Scatter Plot)')
# Create a custom colorbar to show team names
cbar = plt.colorbar(scatter, ticks=range(len(unique_teams)))
cbar.set_ticklabels(unique_teams)
cbar.set_label('Match Winner Team')
plt.tight_layout()
plt.show()
plt.figure(figsize=(8,6))
sns.boxplot(
    data=df,
    x='Toss_Decision',
    y='Won_By',
    palette='Set2'
)
plt.title('Winning Margin by Toss Decision')
plt.xlabel('Toss Decision')
plt.ylabel('Winning Margin')
plt.show()
win_counts = df['Win_Type'].value_counts().sort_index()
plt.figure(figsize=(8,5))
plt.plot(
    win_counts.index,
    win_counts.values,
    marker='o',
    linewidth=2
)
plt.title('Frequency of Win Types')
plt.xlabel('Win Type')
plt.ylabel('Number of Matches')
plt.grid(True)
plt.show()
plt.figure(figsize=(8,6))
sns.violinplot(
    data=df,
    x='Toss_Decision',
    y='Won_By',
    inner='quartile'
)
plt.title('Winning Margin by Toss Decision')
plt.xlabel('Toss Decision')
plt.ylabel('Winning Margin')
plt.show()
plt.figure(figsize=(10,6))
sns.swarmplot(
    data=df,
    x='Toss_Decision',
    y='Match_Winner_Id',
    size=5
)
plt.title('Match Winner IDs by Toss Decision')
plt.xlabel('Toss Decision')
plt.ylabel('Match Winner ID')
plt.show()
team_id_name_pairs = pd.concat([
    df[['Opponent_Team_Id', 'Team name']].rename(columns={'Opponent_Team_Id': 'Team_ID', 'Team name': 'Team_Name'}),
    df[['Opponent_Team_Id', 'OpponentTeam name']].rename(columns={'Opponent_Team_Id': 'Team_ID', 'OpponentTeam name': 'Team_Name'}),
    df[['Match_Winner_Id', 'Team name']].rename(columns={'Match_Winner_Id': 'Team_ID', 'Team name': 'Team_Name'}),
    df[['Match_Winner_Id', 'OpponentTeam name']].rename(columns={'Match_Winner_Id': 'Team_ID', 'OpponentTeam name': 'Team_Name'})
]).drop_duplicates().dropna(subset=['Team_ID', 'Team_Name'])
team_map = team_id_name_pairs.groupby('Team_ID')['Team_Name'].first()
# Map winner IDs to team names
df['Match_Winner_Name'] = df['Match_Winner_Id'].map(team_map)
# Home wins
home_wins = df[df['OpponentTeam name'] == df['Match_Winner_Name']]
home_win_counts = home_wins['OpponentTeam name'].value_counts()
plt.figure(figsize=(9,9))
plt.pie(
    home_win_counts,
    labels=home_win_counts.index,
    autopct='%1.1f%%',
    startangle=90,
    pctdistance=0.8,
    wedgeprops=dict(width=0.4, edgecolor='white')
)
plt.text(
    0, 0,
    "Home\nWins",
    ha='center',
    va='center',
    fontsize=16,
    fontweight='bold'
)
plt.title('Home Ground Wins by Team', fontsize=16, fontweight='bold')
plt.axis('equal')
plt.tight_layout()
plt.show()
df['Venue_Code'] = df['Venue_Name'].astype('category').cat.codes
df['Toss_Code'] = df['Toss_Decision'].astype('category').cat.codes
df['WinType_Code'] = df['Win_Type'].astype('category').cat.codes
# Create 3D Scatter Plot
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111, projection='3d')
scatter = ax.scatter(
    df['Venue_Code'],
    df['Toss_Code'],
    df['WinType_Code'],
    c=df['WinType_Code'],      # Color by Win Type
    cmap='viridis',
    s=40,
    alpha=0.7
)
ax.set_title('3D Scatter Plot of Venue, Toss Decision and Win Type')
ax.set_xlabel('Venue')
ax.set_ylabel('Toss Decision')
ax.set_zlabel('Win Type')
# Show original category names on axes
venue_labels = df['Venue_Name'].astype('category').cat.categories
toss_labels = df['Toss_Decision'].astype('category').cat.categories
win_labels = df['Win_Type'].astype('category').cat.categories
# Limit x-axis labels to avoid clutter (top 10 venues)
ax.set_xticks(range(min(10, len(venue_labels))))
ax.set_xticklabels(venue_labels[:10], rotation=45, ha='right')
ax.set_yticks(range(len(toss_labels)))
ax.set_yticklabels(toss_labels)
ax.set_zticks(range(len(win_labels)))
ax.set_zticklabels(win_labels)
plt.colorbar(scatter, ax=ax, label='Win Type Code')
plt.tight_layout()
plt.show()

EXPLANATION:
- The first loop gives the mean, median, mode, skewness and kurtosis of every numeric column and tells if the data is symmetric, positively or negatively skewed.
- Bar, pie and donut charts show the categorical counts: wins at the top venues, toss decisions and home ground wins.
- A team-id to team-name map is built so the charts show names instead of ids.
- Box plot and violin plot compare the winning margin for each toss decision, the swarm plot shows each winner individually.
- The line plot shows win-type frequency and the 3D scatter plot shows venue, toss decision and win type together.
