<jupyter_start><jupyter_text>**Introduction**You have been recruited as a football analyst in a company - Mchezopesa Ltd and tasked to accomplish the task below.A prediction result of a game between team 1 and team 2, based on who's home and who's away, and on whether or not the game is friendly (include rank in your training).You have two possible approaches (as shown below) given the datasets that will be providedInput: Home team, Away team, Tournament type (World cup, Friendly, Other)Approach 1: Polynomial approachWhat to train given:Rank of home team Rank of away team Tournament type Model 1: Predict how many goals the home team scores.Model 2: Predict how many goals the away team scores.Approach 2: Logistic approachFeature Engineering: Figure out from the home team’s perspective if the game is a Win, Lose or Draw (W, L, D)**Research Question**Predict how many goals the home team scores.Predict how many goals the away team scores.Figure out from the home team’s perspective if the game is a Win, Lose or Draw (W, L, D)**Defining the metric for success**A models that successfully predicts how many goals the home team scores, how many goals the away team scores and determine from the home team’s perspective if the game is a Win, Lose or Draw (W, L, D)  **Data Understanding**<jupyter_code>#importing the relevant libraries
import pandas as pd
import numpy as np
#reading the csv documents
ranking = pd.read_csv('/content/fifa_ranking.csv')
results = pd.read_csv('/content/results.csv')
#studying the datasets
#we start with the ranking datset
print(ranking.shape)
print("****************************************************************************")
ranking.head()
#viewing the results datset
print(results.shape)
print("****************************************************************************")
results.head()
#displaying the dataset information
ranking.info() 
print("****************************************************************************")
print(results.info())
#showing the descriptive statisics for this first dataset
ranking.describe()
#descriptive statistics
results.describe()
#finding the null values
print(ranking.isnull().any())
print("***********************************************")
print(results.isnull().any())<jupyter_output>rank                       False
country_full               False
country_abrv               False
total_points               False
previous_points            False
rank_change                False
cur_year_avg               False
cur_year_avg_weighted      False
last_year_avg              False
last_year_avg_weighted     False
two_year_ago_avg           False
two_year_ago_weighted      False
three_year_ago_avg         False
three_year_ago_weighted    False
confederation              False
rank_date                  False
dtype: bool
***********************************************
date          False
home_team     False
away_team     False
home_score    False
away_score    False
tournament    False
city          False
country       False
neutral       False
dtype: bool<jupyter_text>Both datasets have no null values<jupyter_code>#checking for duplicate values
print("Sum of duplicated records in the ranking datset is " + str(ranking.duplicated().sum()))
print("Sum of duplicated records in the results datset is " + str(results.duplicated().sum()))<jupyter_output>Sum of duplicated records in the ranking datset is 37
Sum of duplicated records in the results datset is 0<jupyter_text>> The results dataset has no duplicate values<jupyter_code>#viewing the exact duplicated records in the ranking dataset
dup_rank = ranking[ranking.duplicated()]
dup_rank<jupyter_output><empty_output><jupyter_text>**Data Cleaning**<jupyter_code>#dropping the columns thatwont be usedin this analysis
colz = ['country_abrv', 'total_points','previous_points', 'rank_change', 'cur_year_avg', 'cur_year_avg_weighted', 'last_year_avg', 'last_year_avg_weighted',
       'two_year_ago_avg', 'two_year_ago_weighted', 'three_year_ago_avg','three_year_ago_weighted', 'confederation']

ranking_colz = ranking.drop(columns=colz)
ranking_colz.head()
#checking the shape of the new dataframe
ranking_colz.shape
#changing the column with the datesto datetime format
anking_colz['rank_date'] = pd.to_datetime(ranking_colz['rank_date'], format='%Y-%m-%d')
ranking_colz.dtypes
#changing the column with the datesto datetime format
results['date'] = pd.to_datetime(results['date'], format='%Y-%m-%d')
results.dtypes
#the two datasets have the date column in common s the will be merged on that axis
#we first extract the year from the date time column
ranking_colz['year'] = ranking_colz['rank_date'].dt.year
ranking_colz.head()
#do the same for the results dataframe
results['year'] = results['date'].dt.year
results.tail()
#rename columns in the ranking table for uniformity
ranking_colz.rename(columns = {'country_full' : 'country'}, inplace = True)
#merging the 2 datasets based on year and home team
df = pd.merge(results,ranking_colz, left_on=['home_team', 'year'], right_on=['home_team', 'year'], how='inner')
df.head()

# Then with the away teams' ranking

df1 = pd.merge(results,ranking_colz, left_on=['away_team', 'year'], right_on=['home_team', 'year'], how='inner')
df1.head(5)
#to merge both home and away
merged = pd.merge(df, df1, how='inner', left_on=['date','home_team', 'away_team','home_score','away_score'], right_on=['date','country','away_team', 
                                                  'home_score', 'away_score']) 
merged.head()
# Checking the shape of the fully merged dataframe.
merged.shape
#checing for duplicated records
erged.duplicated().sum()
#dropping duplicated records
merged.drop_duplicates(keep= 'first', inplace= True)
merged.shape
#check for null records
merged.isnull().sum()<jupyter_output><empty_output><jupyter_text>There are no null records<jupyter_code>#dropping the similar columns from merged dataset
dff = merged.drop(columns=['rank_date_x', 'year_x'])

dff.rename(columns={'rank_x':'home_team_rank', 'rank_y':'away_team_rank'},inplace=True)
dff.head(3)
# using a function to create the status column based on Home team
def my_function(x):
    if x['home_score'] == x['away_score']:
        status = 'Draw'
    elif x['home_score'] > x['away_score']:
        status = 'Win'
    else:
        status = 'loss'
    return status

dff['score'] = dff.apply(my_function, axis=1)<jupyter_output><empty_output><jupyter_text>**Univariate Analysis**<jupyter_code># We will check for outliers in our numerical columns
import matplotlib.pyplot as plt
col= ['home_score', 'away_score','home_team_rank', 'away_team_rank']
for i in col:
  fig = plt.figure(figsize = (10,7))
  plt.boxplot(dff[i])
  plt.title(i)
  plt.show()
# Frequency Table on distribution of tournaments
dff.tournament_x.value_counts().head()
# Histograms of our numerical values
import seaborn as sns
for i in col:
  plt.figure(figsize = (10,3), dpi=100)
  sns.displot(dff[i], kde = True, color = 'aqua')
  plt.title(i, color = 'Black')
  plt.show()
# Bar chart on Status
plt.figure(figsize = (10,5))
dff.groupby('score').size().plot(kind='bar', color='black')
plt.title('Status')
plt.ylabel('Total')
plt.xlabel('score')
plt.show()

# Checking the descriptive statistics
dff.describe()<jupyter_output><empty_output><jupyter_text>**Bivariate Aalysis**<jupyter_code># Home teams with the most wins
win= dff[(dff['score']== 'Win')]
win1 = win.groupby(['home_team'])['score'].size().sort_values(ascending=True).head()
win1.plot(kind = 'bar', title= 'Top 5 Home Team with the most wins', ylabel = 'Wins' , xlabel = 'Country' , figsize =(10,6) , color = 'violet')
plt.show()
# Home teams with the most draws
draws= dff[(dff['score']== 'Draw')]
draw1 = draws.groupby(['home_team'])['score'].size().sort_values(ascending= True).head()
draw1.plot(kind = 'bar', title= 'Top 5 Home Team with the most Draws', ylabel = 'Draws' , xlabel = 'Country' , figsize =(10,6) , color = 'purple')
plt.show()
# Home teams with the most lossess
loss =dff[(dff['score']== 'loss')]
loss1 = loss.groupby(['home_team'])['score'].size().sort_values(ascending= True).head()
loss1.plot(kind = 'bar', title= 'Top 5 Home Team with the most losses', ylabel = 'loss' , xlabel = 'Country' , figsize =(10,6) , color = 'pink')
plt.show()
 #Most Played Tournament

tournament= dff['tournament_x'].value_counts()
print(tournament)<jupyter_output>Friendly                                709099
FIFA World Cup qualification            524073
UEFA Euro qualification                 181776
African Cup of Nations qualification    118481
AFC Asian Cup qualification              41876
                                         ...  
OSN Cup                                    288
Lunar New Year Cup                         265
Copa América qualification                 144
Millennium Cup                             144
Intercontinental Cup                       144
Name: tournament_x, Length: 62, dtype: int64<jupyter_text>**Multivariate Analysis**<jupyter_code># Asses correlation between our variables 
dff.corr()
# Plot a heatmap
fig, heat = plt.subplots(figsize = (10,10))
heat = sns.heatmap(dff.corr(), annot = True, cmap = 'coolwarm')
# Plotting a pairplot of all the numerical values
plt.figure(figsize = (7, 5), dpi=100)
sns.pairplot(dff[col])
# Predict the number of goals scored by the away team having away_score as the dependent variable
# We'll drop columns that are irrelevant in predicting the goals scored by away team

independent = dff.drop(columns=['date', 'home_team', 'away_team', 'away_score', 'tournament_x'])
corr = independent.corr()
corr
# Import libraries
from sklearn.preprocessing import PolynomialFeatures
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression<jupyter_output><empty_output><jupyter_text>**Logistic regression**<jupyter_code>#Applying label encoding to our dataset
from sklearn.preprocessing import LabelEncoder
dff1= dff.apply(LabelEncoder().fit_transform)
dff1.head()
X = dff1.drop(['home_score', 'away_score'], axis = 1)
y = dff1['home_score']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = .2, random_state=0)
# Using our model to make a prediction
from sklearn.linear_model import LinearRegression, LogisticRegression
model = LogisticRegression()
model = model.fit(X_train, y_train)
y_pred = model.predict(X_test)
#comparing the values from the dataset to those predicted
predict = pd.DataFrame({'Actual': y_test, 'Predicted': y_pred})
predict
#checking the model score
model.score(X_test, y_test)<jupyter_output><empty_output><jupyter_text>**Using Cross Validation**<jupyter_code># dependent variable as y
from sklearn.model_selection import KFold, LeaveOneOut
X = dff1.drop(['home_score', 'away_score'], axis = 1).values
y = dff1['home_score'].values

# specifying the number of folds

folds = KFold(n_splits = 5)


# We now assess  models based on the folds we created.

RMSES = [] # An array of RMSEs to keep track of the RSME of each model
count = 1   # starting point # helps to keep track of the model number in training
  
for train_index, test_index in folds.split(X):
    print('\nTraining model ' + str(count))
# Setting up the train and test based on the split determined by KFold
  # With 10 folds we split our data into training and test sets
  
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
  
  # fitting a Logistic regression model
logreg = LogisticRegression()  
logreg=logreg.fit(X_train, y_train)
  
from sklearn import metrics
from sklearn.metrics import confusion_matrix

  # Assess the accuracy of the model
y_pred = logreg.predict(X_test)
  
  # Calculating the RMSES of each model
  # Appending each RMSE into the list earlier created
rmse_value =  np.sqrt(metrics.mean_squared_error(y_test, y_pred))
RMSES.append(rmse_value)
  
 # printing each model RMSE
print('Model ' + str(count) + ' Root Mean Squared Error:',rmse_value)
count = count + 1
pred = pd.DataFrame({'Actual': y_test, 'Predicted': y_pred})
pred
#checking the model score
logreg.score(X_test, y_test)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1310487200660611, 'fraction_numerical': 0.009744013212221304, 'mean_word_length': 4.791965566714491, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '502430', 'license': 'MIT', 'n_tokens_mistral': 3838, 'n_tokens_neox': 3612, 'n_words': 1174, 'path': 'Moringa_Data_Science_Core_W6_Independent_Project_2022_2_Oprah_Muthoni_Python_Notebook.ipynb', 'repo_name': 'muthonioprah/Football-Match-Prediction-Results', 'size': '12110'}