#!/usr/bin/env python # coding: utf-8 # Open In Colab # In[3]: get_ipython().run_line_magic('load_ext', 'watermark') get_ipython().run_line_magic('watermark', '-a "Romell D.Z." -u -d -p pandas,numpy,seaborn,matplotlib') # # Peru road to Russia World Cup 2018 # ![world-cup-18](https://github.com/romellfudi/ExploratoryDataAnalysis/blob/master/snapshot/fifa_world_cup_2018.jpg?raw=1) # In[ ]: # Cargamos las librerías import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # Formateamos una vista legible get_ipython().run_line_magic('matplotlib', 'inline') get_ipython().run_line_magic('config', "InlineBackend.figure_format = 'retina'") # # Preprocessing FIFA DATA # ## Load Data from [SOFIFA] # # [SOFIFA]: # In[ ]: # Data públicada en Enero en Kaggle FIFA18 = pd.read_csv('CompleteDataset.csv', low_memory=False) FIFA18.columns # Indicamos los features a trabajar, dejando a un lado el resto # In[ ]: interesting_columns = [ 'Name', 'Age', 'Nationality', 'Overall', 'Potential', 'Club', 'Value', 'Wage', 'Preferred Positions' ] FIFA18 = pd.DataFrame(FIFA18, columns=interesting_columns) # ## Summarize Data # In[ ]: get_ipython().run_line_magic('load_ext', 'google.colab.data_table') # Vista de la data FIFA18.head() # In[ ]: # Descripción de los features FIFA18.info() # ## Preprocess Data # Cambiamos los vaores de "Value" & "Wage", extrayendo los miles y millones, tienendo los valores numéricos. Los cuales son almacenados en nuevos features 'ValueNum' y 'WageNum'. # In[ ]: # Supporting function for converting string values into numbers def str2number(amount): if amount[-1] == 'M': return float(amount[1:-1])*1000000 elif amount[-1] == 'K': return float(amount[1:-1])*1000 else: return float(amount[1:]) FIFA18['ValueNum'] = FIFA18['Value'].apply(lambda x: str2number(x)) FIFA18['WageNum'] = FIFA18['Wage'].apply(lambda x: str2number(x)) # Sintetizamos el feature 'Preferred Positions' extrayendo únicamente el primer cáracter, omitiendo así la doble posición del jugador # In[ ]: FIFA18['Position'] = FIFA18['Preferred Positions'].str.split().str[0] # Seleccionamos el Grupo donde se encuentra nuestro Perú, Grupo C : \['Francia','Dinamarca','Perú','Australia'\]. # In[ ]: GroupC = FIFA18[FIFA18.Nationality.isin(['France','Denmark','Peru','Australia'])] # Extraemos las medias de los salarios por nacionalidad para el GrupoC # In[ ]: GroupC_Average = FIFA18.groupby('Nationality').agg({'ValueNum':np.mean,'WageNum':np.mean}) GroupC_Average = GroupC_Average.reindex(['France','Denmark','Peru','Australia']) GroupC_Average # # Data Visualization # ## Age # Visualizamos las edades por un histograma. # In[ ]: plt.figure(figsize=(16,8)) sns.set_style("whitegrid") plt.title('Grouping players by Age', fontsize=30, fontweight='bold', y=1.05,) plt.xlabel('Number of players', fontsize=25) plt.ylabel('Players Age', fontsize=25) sns.countplot(x="Age", data=FIFA18, palette="hls"); plt.show() # ## Monto Acomulado (Miles de €) # In[ ]: plt.figure(figsize=(16,8)) sns.set_style("whitegrid") plt.title('Grouping players by Overall', fontsize=30, fontweight='bold', y=1.05,) plt.xlabel('Number of players', fontsize=25) plt.ylabel('Players Age', fontsize=25) sns.countplot(x="Overall", data=FIFA18, palette="hls"); plt.show() # ## Preferred Position # In[ ]: plt.figure(figsize=(16,8)) sns.set_style("whitegrid") plt.title('Grouping players by Preferred Position', fontsize=30, fontweight='bold', y=1.05,) plt.xlabel('Number of players', fontsize=25) plt.ylabel('Players Age', fontsize=25) sns.countplot(x="Position", data=FIFA18, palette="hls"); plt.show() # ## Nationality # In[ ]: FIFA18["Nationality"].value_counts().head(25) # Podemos destacar que una gran cantidad se centraliza en Europa, especialmente en Inglaterra, Alemania, España y Francia # ## Value # Buscamos y listamos a los 20 jugadores que más cobran Netamente # In[ ]: sorted_players = FIFA18.sort_values(["ValueNum"], ascending=False).head(20) sorted_players[["Name" ,"Age" ,"Nationality" ,"Club" ,"Position" ,"Value"]].reset_index(drop=True) # Realizamos una vista de disperción de la valoración del jugador por sus edades e ingresos: # In[ ]: plt.figure(figsize=(16,8)) sns.set_style("whitegrid") plt.title('Players Value according to their Age and Overall', fontsize=30, fontweight='bold', y=1.05,) plt.xlabel('Age', fontsize=25) plt.ylabel('Overall', fontsize=25) age = FIFA18["Age"].values overall = FIFA18["Overall"].values value = FIFA18["ValueNum"].values # Subdividimos los millones para tener una vista legible mediante el área de la ganancia plt.scatter(age, overall, s = value/100000, edgecolors='black') plt.show() # ### 2.6 Wage # Listamos a los 20 jugadores con más recaudación. # In[ ]: sorted_players = FIFA18.sort_values(["WageNum"], ascending=False).head(20) sorted_players[["Name" ,"Age" ,"Nationality" ,"Club" ,"Position" ,"Wage"]].reset_index(drop=True) # Realizamos una vista de disperción de ingresos del jugador por sus edades y Valoración: # In[ ]: plt.figure(figsize=(16,8)) sns.set_style("whitegrid") plt.title('Players Wage according to their Age and Overall', fontsize=30, fontweight='bold', y=1.05,) plt.xlabel('Age', fontsize=25) plt.ylabel('Overall', fontsize=25) age = FIFA18["Age"].values overall = FIFA18["Overall"].values value = FIFA18["WageNum"].values plt.scatter(age, overall, s = value/500, edgecolors='black', color="red") plt.show() # ## 3 - Best Squad Analysis # Seleccionamos una vista más simplee de los jugadores: Nombre, Edad, Nacionalidad, Valoración, Potencial, Club al que actualmente pertenece(puede estar en blanco),Posición, Recaudación, y Salario. # In[ ]: FIFA18 = FIFA18[['Name', 'Age', 'Nationality', 'Overall', 'Potential', 'Club', 'Position', 'Value', 'Wage']] FIFA18.head(10) # ### 3.1 Squad of Highest Overall Players # Cúal es la mejor formación deacuerdo a base de hechos de la FIFA? # In[ ]: def get_best_squad(formation): FIFA18_copy = FIFA18.copy() store = [] for i in formation: store.append([ i, FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax()]]['Name'].to_string(index = False), FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].max(), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax()]]['Age'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax()]]['Club'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax()]]['Value'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax()]]['Wage'].to_string(index = False) ]) FIFA18_copy.drop(FIFA18_copy[FIFA18_copy['Position'] == i]['Overall'].idxmax(), inplace = True) return pd.DataFrame(np.array(store).reshape(11,7), columns = ['Position', 'Player', 'Overall', 'Age', 'Club', 'Value', 'Wage']) # In[ ]: # 4-3-3 squad_433 = ['GK', 'RB', 'CB', 'CB', 'LB', 'CDM', 'CM', 'CAM', 'RW', 'ST', 'LW'] print ('4-3-3') get_best_squad(squad_433)) # In[ ]: # 4-4-2 squad_442 = ['GK', 'RB', 'CB', 'CB', 'LB', 'RM', 'CM', 'CM', 'LM', 'ST', 'ST'] print ('4-4-2') get_best_squad(squad_442) # In[ ]: # 4-2-3-1 squad_4231 = ['GK', 'RB', 'CB', 'CB', 'LB', 'CDM', 'CDM', 'CAM', 'CAM', 'CAM', 'ST'] print ('4-2-3-1') get_best_squad(squad_4231) # Ahora, veamos diferentes posiciones para distintos features. # In[ ]: def get_best_squad_n(formation, nationality, measurement = 'Overall'): FIFA18_copy = FIFA18.copy() FIFA18_copy = FIFA18_copy[FIFA18_copy['Nationality'] == nationality] store = [] for i in formation: store.append([ FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Position'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Name'].to_string(index = False), FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].max(), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Age'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Club'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Value'].to_string(index = False), FIFA18_copy.loc[[FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax()]]['Wage'].to_string(index = False) ]) FIFA18_copy.drop(FIFA18_copy[FIFA18_copy['Position'].str.contains(i)][measurement].idxmax(), inplace = True) return np.mean([x[2] for x in store]).round(2), pd.DataFrame(np.array(store).reshape(11,7), columns = ['Position', 'Player', measurement, 'Age', 'Club', 'Value', 'Wage']) # In[ ]: def get_summary_n(squad_list, squad_name, nationality_list): summary = [] for i in nationality_list: count = 0 for j in squad_list: # for overall rating O_temp_rating, _ = get_best_squad_n(formation = j, nationality = i, measurement = 'Overall') # for potential rating & corresponding value P_temp_rating, _ = get_best_squad_n(formation = j, nationality = i, measurement = 'Potential') summary.append([i, squad_name[count], O_temp_rating.round(2), P_temp_rating.round(2)]) count += 1 return summary # Para cada formación indicamos la mejor estratégia, sin violar las reglas fundamentales del juego. Ejm: 1 portero, etc,etc. # In[ ]: squad_343_strict = ['GK', 'CB', 'CB', 'CB', 'RB|RWB', 'CM|CDM', 'CM|CDM', 'LB|LWB', 'RM|RW', 'ST|CF', 'LM|LW'] squad_442_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'RM', 'CM|CDM', 'CM|CAM', 'LM', 'ST|CF', 'ST|CF'] squad_4312_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CAM|CDM', 'CM|CAM|CDM', 'CAM|CF', 'ST|CF', 'ST|CF'] squad_433_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CAM|CDM', 'CM|CAM|CDM', 'RM|RW', 'ST|CF', 'LM|LW'] squad_4231_strict = ['GK', 'RB|RWB', 'CB', 'CB', 'LB|LWB', 'CM|CDM', 'CM|CDM', 'RM|RW', 'CAM', 'LM|LW', 'ST|CF'] # In[ ]: squad_list = [squad_343_strict, squad_442_strict, squad_4312_strict, squad_433_strict, squad_4231_strict] squad_name = ['3-4-3', '4-4-2', '4-3-1-2', '4-3-3', '4-2-3-1'] # # 3 Group C # ## 3.1 France # # Extramos diferentes posiciónes que pueden generarse para Francia, juntamente con el promedio que generan y sus ratings. # In[ ]: France = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['France'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential']) France.set_index('Nationality', inplace = True) France[['Overall', 'Potential']] = France[['Overall', 'Potential']].astype(float) France # Veamos, la mejor estratégia para Francia sería usar 4-3-3; mientra que las estratégias 4-4-2, and 4-2-3-1 son las que le siguen en dicho orden. Los mejores 11 con una estratégia 4-3-3 brinda actualmente sus mejores partidos hasta la fecha, pero mientras una alineación 4-4-2 le brinda mayor potencial máximo. # In[ ]: rating_433_FR_Overall, best_list_433_FR_Overall = get_best_squad_n(squad_433_strict, 'France', 'Overall') print('-Overall-') print('Average rating: {:.1f}'.format(rating_433_FR_Overall)) best_list_433_FR_Overall # In[ ]: rating_442_FR_Potential, best_list_442_FR_Potential = get_best_squad_n(squad_442_strict, 'France', 'Potential') print('-Potential-') print('Average rating: {:.1f}'.format(rating_442_FR_Potential)) best_list_442_FR_Potential # ![griezmann](https://github.com/romellfudi/ExploratoryDataAnalysis/blob/master/snapshot/griezmann.jpeg?raw=1) # ## 3.2 Denmark # Extramos diferentes posiciónes que pueden generarse para Dinamarca, juntamente con el promedio que generan y sus ratings. # In[ ]: Denmark = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Denmark'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential']) Denmark.set_index('Nationality', inplace = True) Denmark[['Overall', 'Potential']] = Denmark[['Overall', 'Potential']].astype(float) Denmark # Como podemos apreciar tenemos dos picos de estratégias, la formación 4-2-3-1 o 4-3-3; usando el feature 'Potential', podemos indicar que su mejor es usar 4-3-3. La cual indica que nuestro mejor score en general es 79.55, con un potencial máximo de 84.27 # In[ ]: rating_433_DEN_Overall, best_list_433_DEN_Overall = get_best_squad_n(squad_433_strict, 'Denmark', 'Overall') print('-Overall-') print('Average rating: {:.1f}'.format(rating_433_DEN_Overall)) best_list_433_DEN_Overall # In[ ]: rating_433_DEN_Potential, best_list_433_DEN_Potential = get_best_squad_n(squad_433_strict, 'Denmark', 'Potential') print('-Potential-') print('Average rating: {:.1f}'.format(rating_433_DEN_Potential)) best_list_433_DEN_Potential # ![schmeichel](https://github.com/romellfudi/ExploratoryDataAnalysis/blob/master/snapshot/schmeichel.jpg?raw=1) # ## 3.3 Peru # Extramos diferentes posiciónes que pueden generarse para Perú, juntamente con el promedio que generan y sus ratings. # In[ ]: Peru = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Peru'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential']) Peru.set_index('Nationality', inplace = True) Peru[['Overall', 'Potential']] = Peru[['Overall', 'Potential']].astype(float) Peru # Para nuestro Perú, tenemos con una puntuación general la formación 4-4-2 . De la misma forma su potencial se inclina ccon 76.27 sobre la media, seleccionando como esta la mejor formación que hoy en día cuenta. # In[ ]: rating_442_PER_Overall, best_list_442_PER_Overall = get_best_squad_n(squad_442_strict, 'Peru', 'Overall') print('-Overall-') print('Average rating: {:.1f}'.format(rating_442_PER_Overall)) best_list_442_PER_Overall # In[ ]: rating_442_PER_Potential, best_list_442_PER_Potential = get_best_squad_n(squad_442_strict, 'Peru', 'Potential') print('-Potential-') print('Average rating: {:.1f}'.format(rating_442_PER_Potential)) best_list_442_PER_Potential # Pondré una foto del Capitan a pesar que no este en esta data ;) # ![paolo](https://github.com/romellfudi/ExploratoryDataAnalysis/blob/master/snapshot/paolo.jpg?raw=1) # ## 3.5 Australia # Extramos diferentes posiciónes que pueden generarse para Australia, juntamente con el promedio que generan y sus ratings. # In[ ]: Australia = pd.DataFrame(np.array(get_summary_n(squad_list, squad_name, ['Australia'])).reshape(-1,4), columns = ['Nationality', 'Squad', 'Overall', 'Potential']) Australia.set_index('Nationality', inplace = True) Australia[['Overall', 'Potential']] = Australia[['Overall', 'Potential']].astype(float) Australia # De forma similar Australia tiene un score general de 73.55 con la formación 4-3-3 actualmente, por otro lado el potencial máximo que puede alcanzar usando una formación 4-2-3-1 es de 77.90 # In[ ]: rating_433_AU_Overall, best_list_433_AU_Overall = get_best_squad_n(squad_433_strict, 'Brazil', 'Overall') print('-Overall-') print('Average rating: {:.1f}'.format(rating_433_AU_Overall)) best_list_433_AU_Overall # In[ ]: rating_4312_AU_Potential, best_list_4312_AU_Potential = get_best_squad_n(squad_4312_strict, 'Australia', 'Potential') print('-Potential-') print('Average rating: {:.1f}'.format(rating_4312_AU_Potential)) best_list_4312_AU_Potential # ![paolo](https://github.com/romellfudi/ExploratoryDataAnalysis/blob/master/snapshot/langerak.jpg?raw=1) # ## 4 - Final Comparison # # A continuación muestro mediante barrras las puntuciones totales y potencial máximo, para tener una mejor panorama. # In[ ]: teams = ('France', 'Denmark', 'Peru', 'Australia') index = np.arange(len(teams)) average_overall = [rating_433_FR_Overall, rating_433_DEN_Overall, rating_442_PER_Overall,rating_433_AU_Overall] plt.figure(figsize=(16,8)) plt.barh(index, average_overall, align='center', alpha=0.5,color='brrb') plt.yticks(index, teams, fontsize=20) plt.ylabel('National Teams', fontsize=25) plt.xlabel('Average Overall', fontsize=25) plt.axvline(rating_442_PER_Overall) plt.title('Average Overall Rating of Players', fontsize=30, fontweight='bold', y=1.05,) plt.show() # In[ ]: index = np.arange(len(teams)) average_potential = [rating_442_FR_Potential, rating_433_DEN_Potential, rating_442_PER_Potential,rating_433_DEN_Potential] plt.figure(figsize=(16,8)) plt.barh(index, average_potential, align='center',color='brrb', alpha=0.5) plt.yticks(index, teams, fontsize=20) plt.axvline(x=rating_442_PER_Potential) plt.ylabel('National Teams', fontsize=25) plt.xlabel('Average Potential', fontsize=25) plt.title('Average Potential Rating of Players', fontsize=30, fontweight='bold', y=1.05,) plt.show() # In[ ]: GroupC_Average # In[ ]: total_value = GroupC_Average.ValueNum.values * 1000 plt.figure(figsize=(16,8)) plt.barh(index, total_value, align='center', alpha=0.5, color='red') plt.yticks(index, teams, fontsize=20) plt.ylabel('National Teams', fontsize=25) plt.xlabel('Total Value in Million Euros', fontsize=25) plt.title('Total Value of Players', fontsize=30, fontweight='bold', y=1.05,) plt.show() # In[ ]: average_wage = GroupC_Average.WageNum.values plt.figure(figsize=(16,8)) plt.barh(index, average_wage, align='center', alpha=0.5, color='green') plt.yticks(index, teams, fontsize=20) plt.ylabel('National Teams', fontsize=25) plt.xlabel('Average Wages in Thousand Euros (€)', fontsize=25) plt.title('Average Wages of Players', fontsize=30, fontweight='bold', y=1.05,) plt.show() # # Conclusión # Basandonos en el análisis realizado: # * **Francia** tiene la máxima clasificación general media, seguido por **Australia y Dinamarca**. # * **Francia** tiene el máximo score total, seguido by **Peru y Dinamarca**. # * **Francia** tiene la recaudación máxima, seguido por **Peru**. # # Mi apuesta es la siguiente: **Francia y Dinamarca** pasan a octavos de finales, en tercer puesto se encontraría **Perú** del Grupo. # # Si les gusto compartantan este Notebook # ## Copyright & License # # BoostTag E.I.R.L. Romell D.Z. ([@romellfudi](rdominguez@boosttag.com)) # All rights reserved # # https://portfolio.romellfudi.com/ # # Copyright (c) 2018 # MIT. See the LICENSE file for the copyright notice. # In[ ]: