<jupyter_start><jupyter_text>**Author**: _<NAME>_**License:** https://github.com/PradipKumarDas/Competitions/blob/main/LICENSE**Profile & Contact:** [LinkedIn](https://www.linkedin.com/in/daspradipkumar/) | [GitHub](https://github.com/PradipKumarDas) | [Kaggle](https://www.kaggle.com/pradipkumardas) | <EMAIL> (Email) IPL 2021 Match Score Prediction Contest Organized by IIT Madras Online B.Sc. Programme Team A Common Sense based Non-Machine Learning Model<jupyter_code># Imports required packages

import pandas as pd

from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split
# Sets Pandas option to show all columns

pd.set_option('display.max_columns', None)
# Downloads the dataset from cricsheet.org/downloads

!wget https://cricsheet.org/downloads/ipl_csv2.zip -P Data

# Unzips the data

!unzip Data/ipl_csv2.zip -d Data
# Load data for all matches

data = pd.read_csv("Data/all_matches.csv")
# Checks top few rows of the data

data.head()
# Checks bottom rows of the data

data.tail()
# Checks for missing values

data.isna().sum()
# Inserts a new calculated column called "score_off_ball" which is a sum of values in 
# columns "runs_off_bat" and "extras" just after column "extras" to indicate contributing score off the ball
# to make calculating total score at the end of the match easy

data.insert(loc=13, column="score_off_ball", value=data.runs_off_bat + data.extras)<jupyter_output><empty_output><jupyter_text>Checks for venues for duplicates with slightly different names, if any, and updates the rows with the same venue names accordingly<jupyter_code>data.venue.value_counts().sort_index()
# Updates these venues that are mentioned in different names with same name

data.venue[data.venue.str.contains("Brabourne", 
                                                 case=False)] = "Brabourne Stadium"
data.venue[data.venue.str.contains("Chinnaswamy", 
                                                 case=False)] = "M. Chinnaswamy Stadium"
data.venue[data.venue.str.contains("Chidambaram", 
                                                 case=False)] = "M. A. Chidambaram Stadium"
data.venue[data.venue.str.contains(r'Punjab Cricket|IS Bindra|Inderjit Singh Bindra', 
                                                 case=False)] = "IS Bindra Stadium"
data.venue[data.venue.str.contains("Rajiv Gandhi", 
                                                 case=False)] = "Rajiv Gandhi International Cricket Stadium"
data.venue[data.venue.str.contains("Wankhede", 
                                                 case=False)] = "Wankhede Stadium"<jupyter_output>/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  after removing the cwd from sys.path.
/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:6: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  
/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:8: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  
/home/pradip/anaconda3/lib/python[...]<jupyter_text>Checks for teams for duplicates with slightly different names, if any, and updates the rows with the same team names accordingly<jupyter_code>data.batting_team.append(data.bowling_team).value_counts().sort_index()
# Updates team name from "Delhi Daredevils" with the new name "Delhi Capitals"

data.batting_team[data.batting_team.str.contains("Delhi Daredevils", case=False)] = "Delhi Capitals"
data.bowling_team[data.bowling_team.str.contains("Delhi Daredevils", case=False)] = "Delhi Capitals"

# Updates team name from "Kings XI Punjab" with the new name "Punjab Kings"

data.batting_team[data.batting_team.str.contains("Kings XI Punjab", case=False)] = "Punjab Kings"
data.bowling_team[data.bowling_team.str.contains("Kings XI Punjab", case=False)] = "Punjab Kings"

# Updates appropriate team name for "Rising Pune Supergiant"

data.batting_team[data.batting_team.str.contains("Rising Pune Supergiants", case=False)] = "Rising Pune Supergiant"
data.bowling_team[data.bowling_team.str.contains("Rising Pune Supergiants", case=False)] = "Rising Pune Supergiant"<jupyter_output>/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  This is separate from the ipykernel package so we can avoid doing imports until
/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  after removing the cwd from sys.path.
/home/pradip/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:8: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/in[...]<jupyter_text>Let's first build a common sense based non-machine learning model as baselined model.<jupyter_code># First, lets have small dataset for that

data_non_ml = data[data.ball <= 5.6]

data_non_ml = data_non_ml[["match_id", 
                           "venue", 
                           "innings",
                           "batting_team", 
                           "bowling_team", 
                           "score_off_ball"]]
# Resets its index

data_non_ml.reset_index()
# Calculates the match wise total score after end of 6 overs

data_non_ml = data_non_ml.groupby(
    ["match_id", "venue", "innings", "batting_team", "bowling_team"]).score_off_ball.sum()
# Checks how the scores look

data_non_ml
# Resets the multi-index created due to grouping to get tabular data

data_non_ml = data_non_ml.reset_index()
# Checks how to data looks

data_non_ml
# Renames column "score_off_ball" to "score_6_over"

data_non_ml.rename(columns={"score_off_ball": "score_6_over"}, inplace = True)
# Seperates score column from the features data set

y_train = data_non_ml[["score_6_over"]]
X_train = data_non_ml[["match_id", "venue", "innings", "batting_team", "bowling_team"]]
# Splits the available data into train and test data sets

X_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size = 0.2, shuffle = False)
# Resets indexes

X_test.reset_index(drop = True, inplace = True)
y_test.reset_index(drop = True, inplace = True)
# Creates an array to store the predicted innings scores

predictions = []
# Loops through each innings in test data, predicts the innings score and saves it into predictions array

for i, test_match_innings in X_test.iterrows():
    past_matches = X_train[(X_train.venue == test_match_innings.venue) & 
                           (X_train.innings == test_match_innings.innings) & 
                           (X_train.batting_team == test_match_innings.batting_team) & 
                           (X_train.bowling_team == test_match_innings.bowling_team)]
    if past_matches.shape[0] > 0:
        predictions.append(y_train.iloc[past_matches.index].mean()[0])
    else:
        past_matches = X_train[(X_train.innings == test_match_innings.innings) & 
                           (X_train.batting_team == test_match_innings.batting_team) & 
                           (X_train.bowling_team == test_match_innings.bowling_team)]
        if past_matches.shape[0] > 0:
            predictions.append(y_train.iloc[past_matches.index].mean()[0])
        else:
            past_matches = X_train[(X_train.innings == test_match_innings.innings) & 
                               (X_train.batting_team == test_match_innings.batting_team)]
            if past_matches.shape[0] > 0:
                predictions.append(y_train.iloc[past_matches.index].mean()[0])
            else:
                predictions.append(y_train.mean()[0])
# Calculates the mean absolute error against predicted scores across all test data

mean_absolute_error(y_test.score_6_over.array, predictions)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10050079672205782, 'fraction_numerical': 0.005918506715228773, 'mean_word_length': 3.6541313559322033, 'pattern_counts': {'":': 1, '<': 18, '<?xml version=': 0, '>': 20, 'https://': 11, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 15, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '302616', 'license': 'MIT', 'n_tokens_mistral': 2872, 'n_tokens_neox': 2784, 'n_words': 688, 'path': 'IPL_2021_Cricket_Hackathon_IIT_Madras/1_IPL_2021_Match_Score_Prediction_using_Common_Sense_based_Model.ipynb', 'repo_name': 'PradipKumarDas/Competitions', 'size': '8815'}