henriquepgomide / caRtola

Extração de dados da API do CartolaFC, análise exploratória dos dados e modelos preditivos em R e Python - 2014-22. [EN] Data munging, analysis and modeling of CartolaFC - the most popular fantasy football game in Brazil. Data cover years 2014-23.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Algoritmo 2020

ronecharles opened this issue · comments

Ótimo trabalho, show esse algoritmo.

Ao rodar a rodada 1 a 7 2020, tentando o solver para rodada 8
a array de dados está retornando números infinitos, gerando o erro NAN no python.

O mesmo código usado em 2019 funciona perfeitamente.

Tentei substituir os NAN por 0,dai ele roda... mas ele não encontra resposta para o problema, ou seja a sugestão de escalaçao.

Oi, @ronecharles
você pode dar mais detalhes de qual algoritmo/notebook você está tentando rodar?

Bom dia. @arnaldog12

/////////////////////////////////////////////

import pandas as pd

ano = '2020'
url = 'https://raw.githubusercontent.com/henriquepgomide/caRtola/master/data/'+ano+'/'+ano+'-medias-jogadores.csv'
medias = pd.read_csv(url)
medias.head()
medias.shape
medias.columns

qtd_atletas = len(medias['player_id'].unique())
print(qtd_atletas)

posicoes = medias['player_position'].unique()

medias['Rank'] = None
for posicao in posicoes:
rank = medias[medias['player_position'] == posicao].player_id.rank(method='min')
rank = rank - 1
medias.iloc[rank.index,-1] = rank

colunas_unicos = ['Rank','player_id','player_position']
atletas = medias[colunas_unicos].drop_duplicates()

atletas.head()
atletas.shape

partidas = pd.read_csv(r'https://raw.githubusercontent.com/henriquepgomide/caRtola/master/data/'+ano+'/'+ano+'_partidas.csv')
partidas['home_score_norm'] = partidas['home_score'] / max(partidas['home_score'])
partidas['away_score_norm'] = partidas['away_score'] / max(partidas['away_score'])
partidas.head()
partidas.shape

rodada_atual = 7
df_partidas = pd.DataFrame()
for rodada in range(1,rodada_atual):
df_rodada = pd.read_csv(f'https://raw.githubusercontent.com/henriquepgomide/caRtola/master/data/2020/rodada-{rodada}.csv')
df_rodada['round'] = rodada
df_partidas =df_partidas.append(df_rodada,sort=False)

df_partidas.shape
df_partidas = df_partidas[df_partidas['atletas.posicao_id'] != 'tec']
df_partidas = df_partidas.set_index('atletas.atleta_id').join(atletas.set_index('player_id'))

df_partidas.head()
df_partidas['Rank']
df_partidas.drop(df_partidas[df_partidas['Rank'].isnull()].index, inplace=True)
df_partidas['Rank'] = df_partidas['Rank'].astype(int)

import numpy as np

posicao = 'ata'
qtd_atletas = len(atletas[atletas.player_position == posicao])
M = np.zeros((qtd_atletas,qtd_atletas))

M

M.shape

df_partidas_posicao = df_partidas[df_partidas['atletas.posicao_id'] == posicao].copy()

for partida in range(len(partidas)-1): #Vamos deixar a última partida de fora para testes
df_rodada = df_partidas_posicao[df_partidas_posicao['round'] == partidas['round'][partida]]
jogadores_casa = df_rodada[df_rodada['atletas.clube_id'] == partidas['home_team'][partida]]
jogadores_visitantes = df_rodada[df_rodada['atletas.clube_id'] == partidas['away_team'][partida]]

for j_casa in range(len(jogadores_casa)):
    for j_visitante in range(len(jogadores_visitantes)):
        score_casa = 0
        score_visitante = 0
        
        pontos_j_casa = jogadores_casa['atletas.pontos_num'].iloc[j_casa]
        pontos_j_visitante = jogadores_visitantes['atletas.pontos_num'].iloc[j_visitante]
        
        soma =  pontos_j_casa + pontos_j_visitante 
        if soma != 0:
            score_casa = pontos_j_casa / soma
            score_visitante = pontos_j_visitante / soma
        
        j1 = jogadores_casa['Rank'].iloc[j_casa]
        j2 = jogadores_visitantes['Rank'].iloc[j_visitante]
            
        M[j1,j1] = M[j1,j1] + partidas['home_score_norm'][partida] + score_casa
        M[j1,j2] = M[j1,j2] + partidas['away_score_norm'][partida] + score_visitante
        M[j2,j1] = M[j2,j1] + partidas['home_score_norm'][partida] + score_casa
        M[j2,j2] = M[j2,j2] + partidas['away_score_norm'][partida] + score_visitante

M

M = np.nan_to_num(M)
M = M / np.sum(M,axis=1)

evals, evecs = np.linalg.eig(M.T)
evec1 = evecs[:,np.isclose(evals, 1)]

evec1 = evec1[:,0]
stationary = evec1 / evec1.sum()
stationary = stationary.real

stationary

medias[medias.player_position == posicao][list(stationary > 0.015)]

stationaries = {}

for posicao in posicoes:
qtd_atletas = len(atletas[atletas.player_position == posicao])
M = np.zeros((qtd_atletas,qtd_atletas))

df_partidas_posicao = df_partidas[df_partidas['atletas.posicao_id'] == posicao].copy()

for partida in range(len(partidas)-1): #Vamos deixar a última partida de fora para testes
    df_rodada = df_partidas_posicao[df_partidas_posicao['round'] == partidas['round'][partida]]
    jogadores_casa = df_rodada[df_rodada['atletas.clube_id'] == partidas['home_team'][partida]]
    jogadores_visitantes = df_rodada[df_rodada['atletas.clube_id'] == partidas['away_team'][partida]]

    for j_casa in range(len(jogadores_casa)):
        for j_visitante in range(len(jogadores_visitantes)):
            score_casa = 0
            score_visitante = 0

            pontos_j_casa = jogadores_casa['atletas.pontos_num'].iloc[j_casa]
            pontos_j_visitante = jogadores_visitantes['atletas.pontos_num'].iloc[j_visitante]

            soma =  pontos_j_casa + pontos_j_visitante 
            if soma != 0:
                score_casa = pontos_j_casa / soma
                score_visitante = pontos_j_visitante / soma

            def_n_vazada_casa = 0 if partidas['away_score_norm'][partida] > 0 else 1
            def_n_vazada_visitante = 0 if partidas['home_score_norm'][partida] > 0 else 1
            
            if posicao == 'ata':
                pontos_casa = partidas['home_score_norm'][partida] + score_casa
                pontos_visitante = partidas['away_score_norm'][partida] + score_visitante
            elif posicao == 'mei':
                pontos_casa = partidas['home_score_norm'][partida] + def_n_vazada_casa + score_casa
                pontos_visitante = partidas['away_score_norm'][partida] + def_n_vazada_visitante + score_visitante
            else:
                pontos_casa = def_n_vazada_casa + score_casa
                pontos_visitante = def_n_vazada_visitante + score_visitante                  
                
            j1 = jogadores_casa['Rank'].iloc[j_casa]
            j2 = jogadores_visitantes['Rank'].iloc[j_visitante]               

            M[j1,j1] = M[j1,j1] + pontos_casa
            M[j1,j2] = M[j1,j2] + pontos_visitante
            M[j2,j1] = M[j2,j1] + pontos_casa
            M[j2,j2] = M[j2,j2] + pontos_visitante

M = np.nan_to_num(M)
M = M / np.sum(M,axis=1)

evals, evecs = np.linalg.eig(M.T)
evec1 = evecs[:,np.isclose(evals, 1)]

evec1 = evec1[:,0]
stationary = evec1 / evec1.sum()
stationary = stationary.real

stationaries[posicao] = stationary

rodada = 38

df_rodada = df_partidas[df_partidas['round'] == rodada].copy()
df_rodada['Rank'] = df_rodada['Rank'].astype(int)
df_rodada['probs'] = 0

for jogador in range(len(df_rodada)):
posicao = df_rodada.iloc[jogador]['player_position']
rank = df_rodada.iloc[jogador]['Rank']
if rank:
df_rodada.iloc[jogador,-1] = stationaries[posicao][rank]

df_rodada = df_rodada[df_rodada['atletas.status_id'] == 'Provável'].copy()

df_rodada.head()

formacao = {
'ata': 3,
'mei': 3,
'lat': 2,
'zag': 2,
'gol':1
}

cartoletas = 140

df_rodada.set_index('atletas.slug',inplace=True)
z = df_rodada['probs'].to_dict()
c = df_rodada['atletas.preco_num'].to_dict()

dummies_posicao = pd.get_dummies(df_rodada['atletas.posicao_id'])
dummies_posicao = dummies_posicao.to_dict()

from pulp import LpMaximize, LpProblem, lpSum, LpVariable

prob = LpProblem("Melhor_Escalacao", LpMaximize)
y = LpVariable.dicts("Atl",df_rodada.index,0,1,cat='Binary')
prob += lpSum([z[i] * y[i] for i in y])

prob += lpSum([c[i] * y[i] for i in y]) <= cartoletas, "Limite de Cartoletas"
prob += lpSum([dummies_posicao['ata'][i] * y[i] for i in y]) == formacao['ata'], "Quantidade Atacantes"
prob += lpSum([dummies_posicao['lat'][i] * y[i] for i in y]) == formacao['lat'], "Quantidade Laterais"
prob += lpSum([dummies_posicao['mei'][i] * y[i] for i in y]) == formacao['mei'], "Quantidade Meio"
prob += lpSum([dummies_posicao['zag'][i] * y[i] for i in y]) == formacao['zag'], "Quantidade Zagueiros"
prob += lpSum([dummies_posicao['gol'][i] * y[i] for i in y]) == formacao['gol'], "Quantidade Goleiro"

prob.solve()

escalados = []
for v in prob.variables():
if v.varValue == 1:
atleta = v.name.replace('Atl_','').replace('_','-')
escalados.append(atleta)
print(atleta, "=", v.varValue)

colunas = ['atletas.posicao_id','atletas.clube.id.full.name','atletas.pontos_num','atletas.preco_num']
df_rodada.loc[escalados][colunas]

df_rodada.loc[escalados]['atletas.pontos_num'].sum()

df_rodada.loc[escalados]['atletas.preco_num'].sum()

jogar_em_casa = 5

times = {
'Internacional':3,
'Fortaleza':2
}

times_casa = partidas[partidas['round'] == rodada]['home_team']
df_rodada.loc[df_rodada['atletas.clube_id'].isin(times_casa),'probs'] = df_rodada.loc[
df_rodada['atletas.clube_id'].isin(times_casa),'probs'] * (jogar_em_casa / 10 + 1)

for time in times:
df_rodada.loc[df_rodada['atletas.clube.id.full.name'] == time,'probs'] = df_rodada.loc[
df_rodada['atletas.clube.id.full.name'] == time,'probs'] * (times[time] / 10 + 1)

z = df_rodada['probs'].to_dict()

prob = LpProblem("Melhor_Escalacao", LpMaximize)
y = LpVariable.dicts("Atl",df_rodada.index,0,1,cat='Binary')
prob += lpSum([z[i] * y[i] for i in y])

prob += lpSum([c[i] * y[i] for i in y]) <= cartoletas, "Limite de Cartoletas"
prob += lpSum([dummies_posicao['ata'][i] * y[i] for i in y]) == formacao['ata'], "Quantidade Atacantes"
prob += lpSum([dummies_posicao['lat'][i] * y[i] for i in y]) == formacao['lat'], "Quantidade Laterais"
prob += lpSum([dummies_posicao['mei'][i] * y[i] for i in y]) == formacao['mei'], "Quantidade Meio"
prob += lpSum([dummies_posicao['zag'][i] * y[i] for i in y]) == formacao['zag'], "Quantidade Zagueiros"
prob += lpSum([dummies_posicao['gol'][i] * y[i] for i in y]) == formacao['gol'], "Quantidade Goleiro"

prob.solve()

escalados = []
for v in prob.variables():
if v.varValue == 1:
atleta = v.name.replace('Atl_','').replace('_','-')
escalados.append(atleta)
print(atleta, "=", v.varValue)

colunas = ['atletas.posicao_id','atletas.clube.id.full.name','atletas.pontos_num','atletas.preco_num']
df_rodada.loc[escalados][colunas]

df_rodada.loc[escalados]['atletas.pontos_num'].sum()

df_rodada.loc[escalados]['atletas.preco_num'].sum()

/////////////////////////////////////////////

Estou rodando o algoritmo base do repositório, adequado para os dados de 2020 e rodada 8

Uso Python 3, no Windows. Este mesmo algoritmo base 2019, rodada 38, faz a escalação perfeitamente, como no exemplo.

Parece que ao trazer os dados 2020 algo muda...