Wstęp

Dane, których użyję w mojej pracy pochodzą ze strony http://www.football-data.co.uk/. Dotyczą one statystyk meczy piłkarskich Ligii Hiszpańskiej - La Liga Primavera Division w sezonie 2018/19. Na ich podstawie chciałabym przewidzieć czy w danym meczu będzie czerwona kartka. Uważam, że byłoby to ciekawe, aby za pomocą statystyk meczowych być w stanie wywnioskować czy taka sytuacja zaistniała. Również chciałabym się dowiedzieć, które ze zmiennych istotnie wpływają na występowanie czerwonej kartki podczas meczu.

Moje badania przeprowadzę za pomocą 4 metod:

Dane

W danych, które pobrałam ze strony jest wiele zmiennych, np. jakie zespoły grały, ilość goli ,rzutów rożnych, celnych strzałów, fauli, żółtych i czerwonych kartek dla poszczególnych drużyn oraz kursy bukmacherskie.

W tym projekcie chcę przewidzieć za pomocą statystyk meczowych czy będzie czerwona kartka. Nie interesuję mnie więc jakie drużyny grały. Chcę wiedzieć czy w ogóle będzie czerwona kartka, a nie która drużyna ją zdobędzie. W związku z tym sumuje statystyki obu drużyn, aby znać sumę goli, rzutów rożnych itd. podczas meczu.

Przedstawiam poniżej pierwsze 6 obserwacji. W sumie jest ich 190.

SRed SGoals SShots STShots SFouls SCor SYel
0 3 28 12 20 8 2
0 0 15 2 41 5 2
0 3 28 9 19 8 2
0 2 26 7 27 15 5
0 3 24 11 26 10 5
0 3 26 12 25 7 2

Jak widać jest 6 zmiennych objaśniających:

  • SGoals - suma zdobytych goli przez obie drużyn

  • SShots - ilość strzałów podczas meczu

  • STShots - ilość celnych strzałów podczas meczu

  • SFouls - ilość fauli podczas meczu

  • SCor - ilość rzutów rożnych podczas meczu

  • SYel - ilość żółtych kartek podczas meczu

Myślę, że to ilość żółtych kartek i liczba faulów będzie miała największy wpływ na występowanie czerwonej kartki podczas meczu.

Zmienną objaśnianą jest SRed - ilość czerwonych kartek podczas meczu. Interesuję mnie jednak czy w ogóle będzie czerwona kartka. Zamieniam tą zmienną na binarną:

  • 0 - brak czerwonych kartek

  • 1 - będzie min. 1 czerwona kartka

#zamieniam SRed na 0- brak kartki, 1 - kartka (niewazna ilosc)
data$SRed <- ifelse(data$SRed > 0, 1, 0)

Poniżej wykres częstości każdej ze zmiennych:

Najbardziej w oczy rzuca się fakt, iż występowanie czerwonej kartki na meczu to około 20% wszystkich meczy. Goli podczas meczu najczęściej jest 2. Przeciętnie jest 20-30 strzałów, a celnych 5-10. Faulów około 25, rożnych między 8, a 13. Natomiast żółtych kartek najczęściej jest 4-6.

Poniżej podstawowe statystyki opisowe zmiennych:

##       SRed            SGoals           SShots         STShots      
##  Min.   :0.0000   Min.   : 0.000   Min.   :11.00   Min.   : 1.000  
##  1st Qu.:0.0000   1st Qu.: 1.000   1st Qu.:20.25   1st Qu.: 6.000  
##  Median :0.0000   Median : 2.000   Median :25.00   Median : 8.000  
##  Mean   :0.1789   Mean   : 2.532   Mean   :25.29   Mean   : 8.774  
##  3rd Qu.:0.0000   3rd Qu.: 3.000   3rd Qu.:28.75   3rd Qu.:11.000  
##  Max.   :1.0000   Max.   :10.000   Max.   :46.00   Max.   :21.000  
##      SFouls           SCor             SYel       
##  Min.   :15.00   Min.   : 2.000   Min.   : 0.000  
##  1st Qu.:23.00   1st Qu.: 8.000   1st Qu.: 4.000  
##  Median :26.00   Median :10.000   Median : 5.000  
##  Mean   :26.79   Mean   : 9.837   Mean   : 5.126  
##  3rd Qu.:30.00   3rd Qu.:12.000   3rd Qu.: 6.750  
##  Max.   :47.00   Max.   :18.000   Max.   :12.000

Potwierdzają one poprzednie przypuszczenia - szansa na wystąpienie czerwonej kartki to 19%. Statystyki pozostałych zmiennych również potwierdzają to co zauważyłam wcześniej na wykresach częstości.

Budowa zbioru uczącego i testowego

W celu nauki wymienionych wcześniej metod posłużę się zbiorem uczącym, a w celu weryfikacji użyję zbioru testowego. Podzielę swoje dane na te dwa zbiory - zbiór uczący 0.75 obserwacji, a testowy 0.25.

set.seed(2)

division   <- sample(nrow(data), round(0.75*nrow(data)), replace = F)
x.train <- data[ division,-1]
y.train  <- data[ division,1]
x.test <- data[-division,-1]
y.test <- data[-division,1]

train <- data[division,]
test <- data[-division,]  

Poniżej przedstawię wykresy częstości zmiennych w poszczególnych zbiorach, aby sprawdzić, czy obserwacje w zbiorach są porównywalne. Po prawej stronie są wykresy częstości ze zbioru testowego, a po lewej ze zbioru uczącego.

Można zauważyć, że wykresy częstości niektórych zmiennych są do siebie zbliżone, a niektórych już mniej. Niestety nie jest to możliwe by były zawsze takie same. Stosunek ilości występowania czerwonych kartek do braku jest bardzo podobny w obu przypadkach. Uważam ten podział za wystarczająco dobry, aby być w stanie go zaakceptować i przyjąć do przeprowadzenia badania.

Metody przewidywania

Jak już wspomniałam wcześniej w badaniu użyję 4 metod, a następnie postaram wybrać się najlepszą. Po każdej metodzie przedstawię macierz błędów. Biorąc pod uwagę to, że obserwacji, w której występuje czerwona kartka jest mniej dokładność nie będzie najlepszą miarą, za pomocą której będzie można wybrać najlepszą metodę. Do tego wyboru posłużę się miarą czułości i specyficzności.

Metoda k najbliższych sąsiadów

Metodę do wykonam za pomocą funkcji knn. Ma ona parametr k - ile sąsiadów brać pod uwagę. Poniżej przedstawię wykres, który za pomocą funkcji przedstawi wartość czułości i specyficzności dla k od 1 do 30.

Zależy nam na dużej specyficzności - model będzie dobrze rozpoznawać kiedy występuje czerwona kartka. Wybieram więc liczbę sąsiadów 1.

Poniżej macierz błędów i obliczone miary oceny modelu.

data.knn <- knn(train = x.train, test=x.test, cl = y.train, k=1)
confusionMatrix(data.knn, as.factor(y.test))
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 34  8
##          1  4  2
##                                          
##                Accuracy : 0.75           
##                  95% CI : (0.604, 0.8636)
##     No Information Rate : 0.7917         
##     P-Value [Acc > NIR] : 0.8151         
##                                          
##                   Kappa : 0.1111         
##  Mcnemar's Test P-Value : 0.3865         
##                                          
##             Sensitivity : 0.8947         
##             Specificity : 0.2000         
##          Pos Pred Value : 0.8095         
##          Neg Pred Value : 0.3333         
##              Prevalence : 0.7917         
##          Detection Rate : 0.7083         
##    Detection Prevalence : 0.8750         
##       Balanced Accuracy : 0.5474         
##                                          
##        'Positive' Class : 0              
## 

Jak widać specyficzność jest słaba. Tylko w 20% model poprawnie dopasował klasę, gdy występowała rzeczywiście czerwona kartka. Mimo, że dokładność modelu nie jest taka słaba, bo 0.75 to nie sprawdzałby się on dobrze do przewidywania czy podczas meczu będzie czerwona kartka.

Poniżej narysuję krzywą ROC i policzę AUC.

## Area under the curve: 0.5474

Mimo tego, że model jest słaby i tak jest lepszy niż gdyby losowo przyporządkować klasy.

Drzewa decyzyjne

Jest wiele metod za pomocą, których można wykonywać drzewa decyzyjne. Samo pojedyncze drzewo decyzyjne nie jest bardzo skuteczne, ale stosuje się do nich rozszerzenia. Wykonam tutaj algorytm drzew decyzyjnych za pomocą boostingu. Użyję tutaj funkcji gbm. Za ilość drzew przyjmę jej wartość domyślną czyli 100. Poniżej przedstawiam macierz błędu i miary oceny modelu. Za próg odcięcia przyjmuje 0.18, gdyż w całym zbiorze danych czerwona kartka występuje w 18% meczy.

boostTree <- gbm(SRed~.,data=train, n.trees = 100)
## Distribution not specified, assuming bernoulli ...
pred.boost <- predict(boostTree, newdata = test, n.trees = 100, type="response")
pred.test.boost <- ifelse(pred.boost>0.18, 1, 0)
confusionMatrix(as.factor(pred.test.boost), as.factor(y.test))
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 24  3
##          1 14  7
##                                           
##                Accuracy : 0.6458          
##                  95% CI : (0.4946, 0.7784)
##     No Information Rate : 0.7917          
##     P-Value [Acc > NIR] : 0.99402         
##                                           
##                   Kappa : 0.236           
##  Mcnemar's Test P-Value : 0.01529         
##                                           
##             Sensitivity : 0.6316          
##             Specificity : 0.7000          
##          Pos Pred Value : 0.8889          
##          Neg Pred Value : 0.3333          
##              Prevalence : 0.7917          
##          Detection Rate : 0.5000          
##    Detection Prevalence : 0.5625          
##       Balanced Accuracy : 0.6658          
##                                           
##        'Positive' Class : 0               
## 

Widać, że specyficzność jest o wiele lepsza - w 70% model poprawnie przyporządkował fakt, że będzie czerwona kartka. Jednak czułość jest mniejsza - model mylnie przewiduje, że powinna być czerwona kartka.

Poniżej narysuję krzywą ROC i policzę AUC.

## Area under the curve: 0.6658

Model jest dalej słaby, jednak zdecydowanie lepszy od poprzedniego.

Pokażę jeszcze względny wpływ czynników na występowanie czerwonej kartki.

##             var   rel.inf
## SShots   SShots 21.452087
## SFouls   SFouls 20.260183
## SCor       SCor 17.303827
## SYel       SYel 16.447499
## STShots STShots 16.165271
## SGoals   SGoals  8.371134

Jest to bardzo zaskakujące, że suma żółtych kartek, ani faulów nie miała największego wpływu.

Regresja logistyczna

Regresji logistycznej używa się w przypadku, gdy zmienna objaśniana jest zmienną binarną - 0,1. Wykonam ją za pomocą funkcji glm. Podobnie jak wcześniej za próg odcięcia przyjmuję 0.18. Poniżej przedstawiam model powstały w wyniku regresji.

model = glm(SRed~., family = binomial, data=train)
summary(model)
## 
## Call:
## glm(formula = SRed ~ ., family = binomial, data = train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.4503  -0.6479  -0.4851  -0.3512   2.3866  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)  
## (Intercept) -3.24945    1.95510  -1.662   0.0965 .
## SGoals       0.14107    0.15836   0.891   0.3730  
## SShots       0.01112    0.05399   0.206   0.8369  
## STShots     -0.07354    0.09977  -0.737   0.4611  
## SFouls      -0.04517    0.05029  -0.898   0.3690  
## SCor         0.14111    0.07919   1.782   0.0748 .
## SYel         0.26439    0.11523   2.294   0.0218 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 129.03  on 141  degrees of freedom
## Residual deviance: 118.41  on 135  degrees of freedom
## AIC: 132.41
## 
## Number of Fisher Scoring iterations: 5

Na poziomie istotności 0.05 tylko jedna zmienna okazała się istotna - liczba żółtych kartek. Jednak na poziomie istotności 0.1 istotną zmienną jest też liczba rzutów rożnych. Co zastanawiające liczba fauli w ogóle nie wpływa na zmienną objaśnianą.

Tworzę ponownie model tylko ze zmiennymi, które mają istotny wpływ. To na tym modelu będę prowadzić dalszą prognozę.

model2 = glm(SRed~ SYel + SCor, family = binomial, data=train)
summary(model2)
## 
## Call:
## glm(formula = SRed ~ SYel + SCor, family = binomial, data = train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.4730  -0.6368  -0.5188  -0.3637   2.4037  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -4.32379    1.06704  -4.052 5.08e-05 ***
## SYel         0.22419    0.10552   2.125   0.0336 *  
## SCor         0.14883    0.07278   2.045   0.0409 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 129.03  on 141  degrees of freedom
## Residual deviance: 120.54  on 139  degrees of freedom
## AIC: 126.54
## 
## Number of Fisher Scoring iterations: 5

Poniżej przedstawiam prognozę, krzywą ROC i AUC na zbiorze testowym.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 81  9
##          1 37 15
##                                           
##                Accuracy : 0.6761          
##                  95% CI : (0.5925, 0.7521)
##     No Information Rate : 0.831           
##     P-Value [Acc > NIR] : 1               
##                                           
##                   Kappa : 0.2126          
##  Mcnemar's Test P-Value : 6.865e-05       
##                                           
##             Sensitivity : 0.6864          
##             Specificity : 0.6250          
##          Pos Pred Value : 0.9000          
##          Neg Pred Value : 0.2885          
##              Prevalence : 0.8310          
##          Detection Rate : 0.5704          
##    Detection Prevalence : 0.6338          
##       Balanced Accuracy : 0.6557          
##                                           
##        'Positive' Class : 0               
## 

## Area under the curve: 0.6557

Model jest słaby, Specyficzność ma niższą niż model powstały za pomocą drzew decyzyjnych. Za to ma wyższą dokładność.

Poniżej przedstawiam prognozę, krzywą ROC i AUC na zbiorze uczącym.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 24  3
##          1 14  7
##                                           
##                Accuracy : 0.6458          
##                  95% CI : (0.4946, 0.7784)
##     No Information Rate : 0.7917          
##     P-Value [Acc > NIR] : 0.99402         
##                                           
##                   Kappa : 0.236           
##  Mcnemar's Test P-Value : 0.01529         
##                                           
##             Sensitivity : 0.6316          
##             Specificity : 0.7000          
##          Pos Pred Value : 0.8889          
##          Neg Pred Value : 0.3333          
##              Prevalence : 0.7917          
##          Detection Rate : 0.5000          
##    Detection Prevalence : 0.5625          
##       Balanced Accuracy : 0.6658          
##                                           
##        'Positive' Class : 0               
## 

## Area under the curve: 0.6658

Na zbiorze uczącym model ten wypada trochę lepiej. Specyficzność jest na poziomie 70%, tak jak w przypadku drzew. Jednak czułość nie jest na wysokim poziomie.

Klasyfikator naiwny Bayesa

Metodę tę wykonam za pomocą funkcji naive_bayes osobno dla zbioru uczącego oraz osobno dla zbioru testowego.

Poniżej przedstawiam prognozę, krzywą ROC i AUC na zbiorze testowym.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   0   1
##          0 114  21
##          1   4   3
##                                           
##                Accuracy : 0.8239          
##                  95% CI : (0.7512, 0.8827)
##     No Information Rate : 0.831           
##     P-Value [Acc > NIR] : 0.639685        
##                                           
##                   Kappa : 0.1269          
##  Mcnemar's Test P-Value : 0.001374        
##                                           
##             Sensitivity : 0.9661          
##             Specificity : 0.1250          
##          Pos Pred Value : 0.8444          
##          Neg Pred Value : 0.4286          
##              Prevalence : 0.8310          
##          Detection Rate : 0.8028          
##    Detection Prevalence : 0.9507          
##       Balanced Accuracy : 0.5456          
##                                           
##        'Positive' Class : 0               
## 

## Area under the curve: 0.5456

Specyficzność jest bardzo niska, a czułość wysoka. AUC wynosi niewiele ponad 0.5. Model ten nie jest dobry, jest według mnie najsłabszy ze wszystkich.

Poniżej przedstawiam prognozę, krzywą ROC i AUC na zbiorze uczącym.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 35  5
##          1  3  5
##                                           
##                Accuracy : 0.8333          
##                  95% CI : (0.6978, 0.9252)
##     No Information Rate : 0.7917          
##     P-Value [Acc > NIR] : 0.3061          
##                                           
##                   Kappa : 0.4545          
##  Mcnemar's Test P-Value : 0.7237          
##                                           
##             Sensitivity : 0.9211          
##             Specificity : 0.5000          
##          Pos Pred Value : 0.8750          
##          Neg Pred Value : 0.6250          
##              Prevalence : 0.7917          
##          Detection Rate : 0.7292          
##    Detection Prevalence : 0.8333          
##       Balanced Accuracy : 0.7105          
##                                           
##        'Positive' Class : 0               
## 

## Area under the curve: 0.7105

Dla zbioru uczącego wyniki są bardziej zadowalające. Specyficzność tutaj wynosi 50%. Dokładność jest wysoka ze względu na wysoką czułość. Ze względu na bardzo słabą specyficzność model ten nie jest dla mnie satysfakcjonujący.

Wybór właściwej metody

Ze względu na to, że liczba obserwacji (meczy), gdzie pojawiła się czerwona kartka to tylko 18% miara oceny modelu musi być odpowiednio interpretowana. Zakładając ciągle, że na meczu nie byłoby czerwonej kartki to dokładność i tak byłaby wysoka. Należy więc brać pod uwagę specyficzność - w ilu procentach model dobrze przewidział, że będzie czerwona kartka. Im większa czułość - w ilu procentach model dobrze przewidział, że nie będzie czerwonej kartki - tym również lepiej, ale nie da się maksymalizować obu miar. W związku z czym wybrałam maksymalizacji specyficzności i AUC.

Regresja logistyczne i drzewa decyzyjne miały dokładnie takie same wyniki. Decyduję się wybrać regresję logistyczną za finalnie najlepszą, gdyż zmienne istotnie wpływające na występowanie czerwonej kartki miały, moim zdaniem, większy sens niż w przypadku drzew decyzyjnych, gdzie liczba żółtych kartek nie miała za dużego wpływu. Przedstawię poniżej zarówno macierz błędu jak i AUC dla zbioru uczącego oraz testowego.

Dla zbioru uczącego:

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 79  9
##          1 39 15
##                                           
##                Accuracy : 0.662           
##                  95% CI : (0.5779, 0.7391)
##     No Information Rate : 0.831           
##     P-Value [Acc > NIR] : 1               
##                                           
##                   Kappa : 0.1966          
##  Mcnemar's Test P-Value : 2.842e-05       
##                                           
##             Sensitivity : 0.6695          
##             Specificity : 0.6250          
##          Pos Pred Value : 0.8977          
##          Neg Pred Value : 0.2778          
##              Prevalence : 0.8310          
##          Detection Rate : 0.5563          
##    Detection Prevalence : 0.6197          
##       Balanced Accuracy : 0.6472          
##                                           
##        'Positive' Class : 0               
## 
## Area under the curve: 0.6472

Dla zbioru testowego:

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 24  2
##          1 14  8
##                                          
##                Accuracy : 0.6667         
##                  95% CI : (0.5159, 0.796)
##     No Information Rate : 0.7917         
##     P-Value [Acc > NIR] : 0.98605        
##                                          
##                   Kappa : 0.2993         
##  Mcnemar's Test P-Value : 0.00596        
##                                          
##             Sensitivity : 0.6316         
##             Specificity : 0.8000         
##          Pos Pred Value : 0.9231         
##          Neg Pred Value : 0.3636         
##              Prevalence : 0.7917         
##          Detection Rate : 0.5000         
##    Detection Prevalence : 0.5417         
##       Balanced Accuracy : 0.7158         
##                                          
##        'Positive' Class : 0              
## 
## Area under the curve: 0.7158

Podsumowanie

Tak naprawdę żaden z przedstawionych modeli nie był bardzo dobry. Nawet model, który końcowo wybrałam jako najlepszy był średni. Fakt, iż za pomocą tych 4 metod nie udało mi się stworzyć dobrego modelu może wynikać z tego, że piłka nożna jest grą, więc nie da się jej do końca przewidzieć, jest zbyt wiele czynników losowych.

Przedstawię jeszcze sam model regresji logistycznej.

summary(model)
## 
## Call:
## glm(formula = SRed ~ ., family = binomial, data = train)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.4503  -0.6479  -0.4851  -0.3512   2.3866  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)  
## (Intercept) -3.24945    1.95510  -1.662   0.0965 .
## SGoals       0.14107    0.15836   0.891   0.3730  
## SShots       0.01112    0.05399   0.206   0.8369  
## STShots     -0.07354    0.09977  -0.737   0.4611  
## SFouls      -0.04517    0.05029  -0.898   0.3690  
## SCor         0.14111    0.07919   1.782   0.0748 .
## SYel         0.26439    0.11523   2.294   0.0218 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 129.03  on 141  degrees of freedom
## Residual deviance: 118.41  on 135  degrees of freedom
## AIC: 132.41
## 
## Number of Fisher Scoring iterations: 5

Jak już wspomniałam wcześniej zaskoczyło mnie, że liczba fauli nie wpływa istotnie na występowanie czerwonej kartki. Potwierdziło się moje przypuszczenie, dość logiczne, że liczba żółtych kartek będzie wpływać na występowanie czerwonej kartki. Nie jestem znawczynią ani pasjonatką piłki nożnej, więc ciężko mi powiedzieć czy rzeczywiście liczba rzutów rożnych może mieć wpływ na zmienną objaśnianą.

Podsumowując badanie nie okazało się bardzo satysfakcjonujące. Udało się stworzyć średni model i warto się zastanowić bardziej nad wpływem rzutów rożnych na to czy podczas meczu będzie czerwona kartka.