Faz tempo que o jogo FIFA passou o PES em número de fãns e compradores. Eu jogo FIFA desde 2004, nos tempos de Playstation 1 e já tive até o FIFA 98, mesmo não sendo da minha época gamer. O ultimo FIFA que tive foi o 2013, infelizmente meu computador não consegue rodar as versões mais recentes, na verdade ele não roda mais nada, pois aparentemente ele ne liga mais.
Mas é claro, ainda posso brincar de FIFA, só que agora com análise de dados!Todo ano lança um FIFA novo e respectivamente alguma alma bondosa extrai a rica base de dados que esse jogo carrega. Por agora, iremos responder algumas perguntas como:
# Pacotes
library(tidyverse)
library(ggthemes)
library(lubridate)
library(DT)
# Definindo diretório de trabalho
setwd("/cloud/project/Analysis FIFA 19")
# Importando os dados
df1 <- read.csv("data.csv",header = T,sep = ",")
# Estrutura dos dados
str(df1)'data.frame': 18207 obs. of 89 variables:
$ X : int 0 1 2 3 4 5 6 7 8 9 ...
$ ID : int 158023 20801 190871 193080 192985 183277 177003 176580 155862 200389 ...
$ Name : Factor w/ 17194 levels "A. Ábalos","A. Abang",..: 9676 3192 12552 4169 8661 4458 9684 9892 15466 7822 ...
$ Age : int 31 33 26 27 27 27 32 31 32 25 ...
$ Photo : Factor w/ 18207 levels "https://cdn.sofifa.org/players/4/19/100803.png",..: 567 6032 3132 3468 3453 1986 1447 1391 484 4443 ...
$ Nationality : Factor w/ 164 levels "Afghanistan",..: 7 124 21 141 14 14 36 159 141 138 ...
$ Flag : Factor w/ 164 levels "https://cdn.sofifa.org/flags/1.png",..: 123 108 125 115 138 138 2 132 115 114 ...
$ Overall : int 94 94 92 91 91 91 91 91 91 90 ...
$ Potential : int 94 94 93 93 92 91 91 91 91 93 ...
$ Club : Factor w/ 652 levels ""," SSV Jahn Regensburg",..: 215 330 437 377 376 138 474 215 474 62 ...
$ Club.Logo : Factor w/ 679 levels "https://cdn.sofifa.org/flags/103.png",..: 491 553 638 90 30 577 493 491 493 490 ...
$ Value : Factor w/ 217 levels "€0","€1.1M","€1.2M",..: 17 196 19 191 13 214 183 202 155 184 ...
$ Wage : Factor w/ 144 levels "€0","€100K","€105K",..: 95 75 56 50 67 65 78 82 71 138 ...
$ Special : int 2202 2228 2143 1471 2281 2142 2280 2346 2201 1331 ...
$ Preferred.Foot : Factor w/ 3 levels "","Left","Right": 2 3 3 3 3 3 3 3 3 3 ...
$ International.Reputation: int 5 5 5 4 4 4 4 5 4 3 ...
$ Weak.Foot : int 4 4 5 3 5 4 4 4 3 3 ...
$ Skill.Moves : int 4 5 5 1 4 4 4 3 3 1 ...
$ Work.Rate : Factor w/ 10 levels "","High/ High",..: 10 3 4 10 2 4 2 4 4 10 ...
$ Body.Type : Factor w/ 11 levels "","Akinfenwa",..: 6 3 7 5 8 8 5 8 8 8 ...
$ Real.Face : Factor w/ 3 levels "","No","Yes": 3 3 3 3 3 3 3 3 3 3 ...
$ Position : Factor w/ 28 levels "","CAM","CB",..: 23 28 16 7 21 13 21 25 20 7 ...
$ Jersey.Number : int 10 7 10 1 7 10 10 9 15 1 ...
$ Joined : Factor w/ 1737 levels "","Apr 1, 2008",..: 776 796 249 783 255 784 105 801 98 836 ...
$ Loaned.From : Factor w/ 342 levels "","1. FC Köln",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Contract.Valid.Until : Factor w/ 37 levels "","2018","2019",..: 5 6 6 4 7 4 4 5 4 5 ...
$ Height : Factor w/ 22 levels "","5'1","5'10",..: 10 15 12 17 4 11 11 13 13 15 ...
$ Weight : Factor w/ 58 levels "","110lbs","115lbs",..: 23 34 19 27 21 25 17 37 33 38 ...
$ LS : Factor w/ 94 levels "","31+2","32+2",..: 93 94 88 1 85 87 75 92 67 1 ...
$ ST : Factor w/ 94 levels "","31+2","32+2",..: 93 94 88 1 85 87 75 92 67 1 ...
$ RS : Factor w/ 94 levels "","31+2","32+2",..: 93 94 88 1 85 87 75 92 67 1 ...
$ LW : Factor w/ 106 levels "","25+2","27+2",..: 106 105 105 1 104 105 101 103 71 1 ...
$ LF : Factor w/ 103 levels "","27+2","29+2",..: 103 102 101 1 98 100 95 99 68 1 ...
$ CF : Factor w/ 103 levels "","27+2","29+2",..: 103 102 101 1 98 100 95 99 68 1 ...
$ RF : Factor w/ 103 levels "","27+2","29+2",..: 103 102 101 1 98 100 95 99 68 1 ...
$ RW : Factor w/ 106 levels "","25+2","27+2",..: 106 105 105 1 104 105 101 103 71 1 ...
$ LAM : Factor w/ 102 levels "","27+2","28+2",..: 102 100 101 1 100 101 99 97 69 1 ...
$ CAM : Factor w/ 102 levels "","27+2","28+2",..: 102 100 101 1 100 101 99 97 69 1 ...
$ RAM : Factor w/ 102 levels "","27+2","28+2",..: 102 100 101 1 100 101 99 97 69 1 ...
$ LM : Factor w/ 101 levels "","27+2","28+2",..: 101 99 99 1 99 100 98 96 70 1 ...
$ LCM : Factor w/ 93 levels "","30+2","31+2",..: 88 83 83 1 92 85 93 79 70 1 ...
$ CM : Factor w/ 93 levels "","30+2","31+2",..: 88 83 83 1 92 85 93 79 70 1 ...
$ RCM : Factor w/ 93 levels "","30+2","31+2",..: 88 83 83 1 92 85 93 79 70 1 ...
$ RM : Factor w/ 101 levels "","27+2","28+2",..: 101 99 99 1 99 100 98 96 70 1 ...
$ LWB : Factor w/ 96 levels "","30+2","31+2",..: 55 58 58 1 83 60 93 67 91 1 ...
$ LDM : Factor w/ 100 levels "","28+2","29+2",..: 50 51 49 1 84 55 92 66 97 1 ...
$ CDM : Factor w/ 100 levels "","28+2","29+2",..: 50 51 49 1 84 55 92 66 97 1 ...
$ RDM : Factor w/ 100 levels "","28+2","29+2",..: 50 51 49 1 84 55 92 66 97 1 ...
$ RWB : Factor w/ 96 levels "","30+2","31+2",..: 55 58 58 1 83 60 93 67 91 1 ...
$ LB : Factor w/ 99 levels "","29+2","30+2",..: 49 54 52 1 79 52 91 65 99 1 ...
$ LCB : Factor w/ 109 levels "","25+2","27+2",..: 30 44 31 1 71 35 81 65 109 1 ...
$ CB : Factor w/ 109 levels "","25+2","27+2",..: 30 44 31 1 71 35 81 65 109 1 ...
$ RCB : Factor w/ 109 levels "","25+2","27+2",..: 30 44 31 1 71 35 81 65 109 1 ...
$ RB : Factor w/ 99 levels "","29+2","30+2",..: 49 54 52 1 79 52 91 65 99 1 ...
$ Crossing : int 84 84 79 17 93 81 86 77 66 13 ...
$ Finishing : int 95 94 87 13 82 84 72 93 60 11 ...
$ HeadingAccuracy : int 70 89 62 21 55 61 55 77 91 15 ...
$ ShortPassing : int 90 81 84 50 92 89 93 82 78 29 ...
$ Volleys : int 86 87 84 13 82 80 76 88 66 13 ...
$ Dribbling : int 97 88 96 18 86 95 90 87 63 12 ...
$ Curve : int 93 81 88 21 85 83 85 86 74 13 ...
$ FKAccuracy : int 94 76 87 19 83 79 78 84 72 14 ...
$ LongPassing : int 87 77 78 51 91 83 88 64 77 26 ...
$ BallControl : int 96 94 95 42 91 94 93 90 84 16 ...
$ Acceleration : int 91 89 94 57 78 94 80 86 76 43 ...
$ SprintSpeed : int 86 91 90 58 76 88 72 75 75 60 ...
$ Agility : int 91 87 96 60 79 95 93 82 78 67 ...
$ Reactions : int 95 96 94 90 91 90 90 92 85 86 ...
$ Balance : int 95 70 84 43 77 94 94 83 66 49 ...
$ ShotPower : int 85 95 80 31 91 82 79 86 79 22 ...
$ Jumping : int 68 95 61 67 63 56 68 69 93 76 ...
$ Stamina : int 72 88 81 43 90 83 89 90 84 41 ...
$ Strength : int 59 79 49 64 75 66 58 83 83 78 ...
$ LongShots : int 94 93 82 12 91 80 82 85 59 12 ...
$ Aggression : int 48 63 56 38 76 54 62 87 88 34 ...
$ Interceptions : int 22 29 36 30 61 41 83 41 90 19 ...
$ Positioning : int 94 95 89 12 87 87 79 92 60 11 ...
$ Vision : int 94 82 87 68 94 89 92 84 63 70 ...
$ Penalties : int 75 85 81 40 79 86 82 85 75 11 ...
$ Composure : int 96 95 94 68 88 91 84 85 82 70 ...
$ Marking : int 33 28 27 15 68 34 60 62 87 27 ...
$ StandingTackle : int 28 31 24 21 58 27 76 45 92 12 ...
$ SlidingTackle : int 26 23 33 13 51 22 73 38 91 18 ...
$ GKDiving : int 6 7 9 90 15 11 13 27 11 86 ...
$ GKHandling : int 11 11 9 85 13 12 9 25 8 92 ...
$ GKKicking : int 15 15 15 87 5 6 7 31 9 78 ...
$ GKPositioning : int 14 14 15 88 10 8 14 33 7 88 ...
$ GKReflexes : int 8 11 11 94 13 8 9 37 11 89 ...
$ Release.Clause : Factor w/ 1245 levels "","€1.1M","€1.2M",..: 295 84 296 106 234 189 104 170 24 123 ...
# Mudando os dados
## Valores dos Jogadores
df1 <- df1 %>%
mutate(Valor = ifelse(str_detect(Value, "K"), 1000, ifelse(str_detect(Value, "M"), 1000000, 1))) %>%
mutate(Value = as.numeric(str_extract(Value, "[[:digit:]]+\\.*[[:digit:]]*")) * Valor)
## Salários
df1 <- df1 %>%
mutate(salario = ifelse(str_detect(Value, "K"), 1000, ifelse(str_detect(Value, "M"), 1000000, 1))) %>%
mutate(Wage = as.numeric(str_extract(Value, "[[:digit:]]+\\.*[[:digit:]]*")) * salario)
## Datas
df1 <- df1 %>%
mutate(Data = mdy(df1$Joined)) A base de dados contém 18207 linhas e 94 colunas. Não usarei todas as variaveis na análise,embora vi gente fazendo coisas legais com elas, vamos nos concentrar em poucas variaveis.
df1 %>%
filter(Club != "") %>%
group_by(Club) %>%
summarise(Total = sum(Overall)) %>%
arrange(desc(Total)) %>%
slice(1:20) %>%
ggplot(aes(reorder(Club,Total),Total)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_fivethirtyeight()Para quem não sabe, a variavel overall é como se fosse a força de cada jogador. É um número que varia de 1 a 100 e quanto maior for, mais forte(decisivo) o jogador é. Como nesse caso agragamos por clube, podemos ver quais clubes tem elencos com jogadores mais “fortes”.
O que chama a atenção são clubes como Hoffenheim e RC Celta na lista dos 20 clubes mais fortes do jogo. Pra quem acompanha futebol, como foi a temporada de 2018 - 2019 desses clubes em suas ligas?
df1 %>%
filter(Nationality != "") %>%
group_by(Nationality) %>%
summarise(Total = sum(Overall)) %>%
arrange(desc(Total)) %>%
slice(1:20) %>%
ggplot(aes(reorder(Nationality,Total),Total)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_fivethirtyeight()df2 <- df1 %>%
filter(Nationality != "") %>%
group_by(Nationality) %>%
summarise(Total = sum(Overall)) %>%
arrange(desc(Total)) %>%
slice(1:20) %>%
select(Nationality)Esse gráfico engana quem não conhece sua base de dados. Como estamos somando o overall por país, países com maior numero de jogadores tendem a ter o maior overall. Porém, podemos ver o nivel desses jogadores de outra forma, como no grafico abaixo:
left_join(df2,df1) %>%
ggplot(aes(reorder(Nationality,Overall),Overall)) +
geom_boxplot() +
coord_flip() +
theme_fivethirtyeight() +
scale_y_continuous(breaks = seq(from = 0,to = 95,by = 5))Para quem não sabe ler um box-plot (gráfico acima), atente - se a linha preta no meio da caixa, que significa a mediana do overall de cada país. Ou seja ela, a esquerda da linha preta representa os 50% dos jogadores mais fracos do país e a direita da linha os 50% mais fortes.
Podemos reparar que Portugal e Brasil detém a linha mais alta, ou seja, os 50% dos jogadores mais fracos desses países tem até 72 de overall, enquanto que na Inglaterra esse número é de 64.
Agora repare nos pontinhos pretos no fim da cada caixa a direita. Eles representam os outliers, ou seja, jogadores fora do padrão de seu prórpio país, podemos chama - los de craques. No lado contrário, à esquerda, podemos chama - los de rodinei (Lateral do Flamengo), que são os jogadores que destoam dos outros pelo lado ruim.
library(ggalt)
df1 %>%
filter(Club != "") %>%
group_by(Club) %>%
summarise(Potencial = sum(Potential),
Overall = sum(Overall),
Crescimento = sum(Potencial- Overall)) %>%
arrange(desc(Crescimento)) %>%
slice(1:20) %>%
ggplot(aes(x=Overall, xend=Potencial, y=reorder(Club,Overall), group=Club)) +
geom_dumbbell(colour = "grey",
colour_x = "blue",
colour_xend = "red",
size = 1.2,
size_x = 3,
size_xend = 3) +
theme_fivethirtyeight() +
scale_x_continuous(breaks = seq(from = 1500,to = 3000,by = 250))Breve explicação: Além do Overall, existe uma variavel chamada potential, ou seja, é o overall final que um jogador ainda pode atingir.
É incrivel que alguns times que já estão entre os melhores ainda tem grande potencial de crescimento. Barcelo e Man City já figuram entre os melhores times do jogo, mas ainda tem potencial de serem melhores.
df1 %>%
filter(Club != "") %>%
group_by(Club) %>%
summarise(Taxa = sum(Value)/sum(Wage)) %>%
arrange(desc(Taxa)) %>%
slice(1:20) %>%
ggplot(aes(reorder(Club,Taxa),Taxa)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_fivethirtyeight() +
scale_y_continuous(breaks = seq(from = 0,to = 10,by = 1))Esse gráfico é interessante. Ele nos diz qual clube paga menos de salario de acordo com o valor de seu elenco. Se pegarmos o exemplo do Atalanta, ele paga 3.5 vezes aproximadamente menos de salario para os seus jogadores em relaçao a soma dos seus valores de mercado.
df1 %>%
mutate(Tempo_Casa = as.Date("2018-09-01") - Data) %>%
select(Name,Club,Tempo_Casa) %>%
arrange(desc(Tempo_Casa)) %>%
slice(1:20) %>%
ggplot(aes(reorder(Name,Tempo_Casa),Tempo_Casa)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_fivethirtyeight() +
scale_y_continuous(breaks = seq(from = 0,to = 10000,by = 1000)) +
geom_label(aes(x = Name, y = Tempo_Casa, label = Club),
hjust = 1,
vjust = 0.5,
colour = "white",
fill = NA,
label.size = NA,
family="Helvetica",
size = 3) Em número de dias, parece que jogadores fora das grandes ligas são os que mais tempo permanecem em seus clubes, com algumas exceções como De Rossi, jogador da Roma. Porém recentemente ele se transferiu para o Boca Juniors.
df1 %>%
mutate(Tempo_Casa = as.Date("2018-09-01") - Data) %>%
select(Name,Club,Tempo_Casa) %>%
group_by(Club) %>%
summarise(Tempo_Total = sum(Tempo_Casa,na.rm = T)) %>%
filter(Club != "") %>%
arrange(desc(Tempo_Total)) %>%
slice(1:20) %>%
ggplot(aes(reorder(Club,Tempo_Total),Tempo_Total)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_fivethirtyeight() +
scale_y_continuous(breaks = seq(from = 0,to = 50000,by = 5000)) Aqui temos a soma de dias dos tempos em que cada jogador está no seu clube até a data de 01/09/2018. Parece que os times japoneses são os que mais retém os jogadores.
Algumas coisas bem obvias podem ser vistas aqui. Tanto a curva de Potencial quanto a de Overall tendem a ser exponencias ao valor dos jogadores. Ou seja, quanto maior uma dessas variaveis, maior tende a ser o seu valor de mercado.