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.
MIT License
451 stars 253 forks source link

Algoritmo 2020 #74

Open ronecharles opened 4 years ago

ronecharles commented 4 years ago

Ó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.

arnaldog12 commented 4 years ago

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

ronecharles commented 4 years ago

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...