#importando bibliotecas que iremos usar

%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import warnings
import os
from numpy import arange
from scipy.stats import skew
from sklearn.utils import shuffle
from scipy.stats.stats import pearsonr
from sklearn import cross_validation, metrics
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.linear_model import Ridge, Lasso
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import ElasticNet as ElasticNetImpl
from sklearn.preprocessing import LabelEncoder
from subprocess import check_output
from sklearn.utils import shuffle
from scipy.stats import norm
from sklearn.preprocessing import StandardScaler
from scipy import stats
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.grid_search import GridSearchCV

warnings.filterwarnings('ignore')

"""
Explanation: Projeto 3 Ciência dos Dados.
Tema: FIFA18
Objetivo: Tendência de um jogador virar craque
Alunos: Augusto Franco e Pedro Daher
O objetivo deste trabalho é averiguar qual a tendência do jogador virar craque, baseadoem atributos do mesmo.
End of explanation
"""


fifa = pd.read_csv('CompleteDataset.csv')

"""
Explanation: Importa a planilha que contem os dados utilizados. Esta planilha foi importada de www.kaggle.com
End of explanation
"""


def extrai(value):
    out = value.replace('€', '')
    if 'M' in out:
        out = float(out.replace('M', ''))*1000000
    elif 'K' in value:
        out = float(out.replace('K', ''))*1000
    return float(out)

fifa['Value'] = fifa['Value'].apply(lambda x: extrai(x))
fifa['Wage'] = fifa['Wage'].apply(lambda x: extrai(x))

"""
Explanation: Normaliza a coluna 'Value' (valor do jogador) e a coluna 'Wage' (salário do jogador por semana)
End of explanation
"""


fifa = shuffle(fifa)

train = fifa.iloc[:15000]
test = fifa.iloc[15000:]

"""
Explanation: Embaralha e divide a planilha em 2. Uma contendo 15000 jogadores (train) e outra com aproximadamente 3000 jogadores (test)
End of explanation
"""


x = [ 'Potential', 'Overall', 'Wage', 'Age', 'Special'] #atributos utilizados para calcular um value
y = ['Value'] #objetivo

"""
Explanation: Escolhendo os valores que serão utilizados para calcular nosso objetivo, que é o "Value"
End of explanation
"""


var = 'Value'
data = pd.concat([train['Overall'], train[var]], axis=1)
data.plot.scatter(x=var, y='Overall', ylim=(60,100), xlim=(0,150000000));

"""
Explanation: Verificando o quanto Overall influencia no Valor do jogador
End of explanation
"""


var = 'Wage'
data = pd.concat([train['Overall'], train[var]], axis=1)
data.plot.scatter(x=var, y='Overall', ylim=(40,100), xlim=(0,600000));

"""
Explanation: Verificando o quanto Overall influencia no Valor do jogador
End of explanation
"""


corr = fifa.drop('ID', axis = 1).corr()

fig = plt.figure(figsize=(20,16))

ax = sns.heatmap(corr, 
                 xticklabels=corr.columns.values,
                 yticklabels=corr.columns.values,
                 linewidths=0.25,
                 vmax=1.0, 
                 square=True, 
                 cmap = 'PuBu', 
                 linecolor='black', 
                 annot=False
                )

"""
Explanation: Verifica, através da cor azul, quais as variáveis que mais influenciam a variável 'Value'. Quanto mais próximo de azul escuro for o quadrado da intersecção, maior é a correlação entre as duas variáveis.
End of explanation
"""


train.drop(["Photo", "Flag","Club Logo","Name"],1,inplace=True)

train.drop("ID",1,inplace=True)

l_encode = LabelEncoder()
obj_feat = ["Club", "Nationality","Preferred Positions"]
for var in obj_feat:
    train[var] = l_encode.fit_transform(train[var].astype(str))
train.shape

def clean_values(x):
    try:
        if len(x)>2:
            y = x[:2]
            return y
        else:
            return x
    except TypeError:
        return x
columns_to_clean = [col for col in train.columns if col not in ["Age","Nationality",
                                                                  "Overall","Potential",
                                                                 "Club","Value","Wage",
                                                                  "Special"]]
for col in columns_to_clean:
    train[col] = train[col].apply(lambda x : clean_values(x))

train = train.dropna(axis=1, how="any")

def modelfit(alg, dtrain, features, performCV=True, printFeatureImportance=True, cv_folds=10):
    
    alg.fit(dtrain[features],dtrain["Value"] )
        
    
    dtrain_predictions = alg.predict(dtrain[features])

   
    cv_score = cross_validation.cross_val_score(alg, dtrain[features], dtrain["Value"], cv=cv_folds,
                                                scoring='neg_mean_squared_error')
    cv_score = np.sqrt(np.abs(cv_score))
    
    
    print ("\nModel Report")
    print ("RMSE : %.4g" % np.sqrt(metrics.mean_squared_error(dtrain["Value"], dtrain_predictions)))
    print ("CV Score : Mean - %.4g | Std - %.4g | Min - %.4g | Max - %.4g" % (np.mean(cv_score),
                                                                             np.std(cv_score),np.min(cv_score),
                                                                              np.max(cv_score)))
    if printFeatureImportance:
        feat_imp = pd.Series(alg.feature_importances_, features).sort_values(ascending=False)
        feat_imp.plot(kind='bar', title='Feature Importances')
        plt.ylabel('Feature Importance Score')

#Grau de correlação entre outras variáveis, em relação ao valor
features = [i for i in train.columns if i != "Value"]
target = "Value"
gbm0 = GradientBoostingRegressor(random_state=7)
modelfit(gbm0, train, features)

"""
Explanation: Faremos, agora, a correlação entre as variáveis, com o alvo em Value. Agora o gráfico será plotado em barras e possuirá qual o valor da correlação entre as variáveis
End of explanation
"""


#Jogadores com salário igual a 0.8K foram lidos como sendo 0. Para corrigir isso, colocamos valores e salários abaixo de 1K como 
#sendo iguais a 1K (arredondamento pra cima).
train.Value[train.Value==0]=1
train.Wage[train.Wage==0]=1

sns.distplot(np.log(train['Value']), fit=norm);
fig = plt.figure()
res = stats.probplot(np.log(train['Value']), plot=plt)

"""
Explanation: O primeiro gráfico apresenta a frequência dos valores dos jogadores. Já o segundo gráfico traduz o primeiro em pontos e possui uma reta que satisfaz estes vários pontos. Nota-se que há uma sequência no segundo gráfico de valores iguais a zero. Isso ocorre pois os valores entre os salários dos jogadores são muito discrepantes (exemplo: um jogador bom ganha 600.000 euros por semana, enquanto outros ganham 800 euros por semana). Estes que ganham 800 euros por semana foram arredondados para 0.8 mil euros por semana, e, devido à enorme discrepância, pode-se igualá-los a zero.
End of explanation
"""


def ridge_regression(train, x, alpha):
    ridgereg = Ridge(alpha=alpha,normalize=True)
    ridgereg.fit(train[x],train['Value'])
    y_pred = ridgereg.predict(train[x])
    return(y_pred)

ridge = ridge_regression(train, x, 1e-20)
plt.plot(train['Value'],ridge,'.', color="blue")
plt.axis([0, 130000000, 0, 130000000])
plt.xlabel("Valor real")
plt.ylabel("Valor premeditado")
plt.show()

r_R = ridge_regression(test, x, 1e-20)
print((mean_squared_error(test['Value'],r_R))**(1/2))

"""
Explanation: Função que realiza a regressão de Ridge na planilha Treino
End of explanation
"""


ridgetest = ridge_regression(test, x, 1e-20)

plt.plot(test['Value'],ridgetest,'.', color="red")
plt.axis([0, 130000000, 0, 130000000])
plt.xlabel("Valor real")
plt.ylabel("Valor premeditado")
plt.show()

"""
Explanation: Regressão de Ridge na planilha de teste
End of explanation
"""


