1 Pendahuluan

1.1 Latar Belakang

Industri sepak bola modern semakin bergantung pada analisis data untuk mengevaluasi performa pemain secara objektif. Setiap pemain sepak bola memiliki profil atribut yang kompleks, mencakup kemampuan teknis, fisik, dan mental yang dinilai melalui puluhan indikator. Dalam konteks analisis statistik, keberadaan banyak variabel secara simultan menimbulkan tantangan tersendiri, terutama karena atribut-atribut tersebut cenderung saling berkorelasi satu sama lain.

Sebagai contoh, pemain dengan kemampuan short passing yang tinggi pada umumnya juga memiliki nilai ball control dan vision yang tinggi. Demikian pula, atribut dribbling sering kali berkorelasi erat dengan agility dan acceleration. Kondisi ini menunjukkan bahwa terdapat redundansi informasi di antara variabel-variabel tersebut, sehingga analisis langsung menggunakan seluruh variabel secara serentak dapat menghasilkan model yang tidak efisien dan sulit diinterpretasikan.

Untuk mengatasi permasalahan tersebut, diperlukan metode reduksi dimensi yang mampu meringkas informasi dari banyak variabel yang berkorelasi menjadi sejumlah kecil komponen yang tidak saling berkorelasi namun tetap merepresentasikan sebagian besar variasi data. Metode yang umum digunakan untuk tujuan ini adalah Principal Component Analysis (PCA). PCA merupakan teknik statistik multivariat yang mentransformasi variabel-variabel asli menjadi komponen-komponen utama (principal components) yang ortogonal satu sama lain, sehingga redundansi informasi dapat dieliminasi secara efektif (Johnson & Wichern, 2007).

Laporan ini merupakan tahap awal dari analisis multivariat menggunakan dataset FC 26, yang mencakup pembersihan data dan eksplorasi data (Exploratory Data Analysis/EDA) sebagai dasar penerapan PCA pada tahap analisis berikutnya.

1.2 Deskripsi Dataset

Dataset yang digunakan dalam analisis ini adalah FC 26 Player Dataset, yang bersumber dari platform Kaggle. Dataset ini memuat data atribut pemain dari video game simulasi sepak bola FC 26 (FIFA 26), yang secara luas digunakan sebagai proksi penilaian kemampuan pemain sepak bola nyata.

library(tidyverse)
library(psych)
library(corrplot)
library(knitr)

# Membaca dataset
# Catatan: letakkan file CSV dalam folder yang sama dengan file Rmd ini.
data_path <- "FC26_20250921.csv"
if (!file.exists(data_path)) {
  stop("File FC26_20250921.csv tidak ditemukan. Pastikan file CSV berada dalam folder kerja yang sama dengan file Rmd.")
}

df_raw <- read.csv(data_path, stringsAsFactors = FALSE)

# Menampilkan dimensi dataset
cat("Jumlah observasi (baris):", nrow(df_raw), "\n")
## Jumlah observasi (baris): 18405
cat("Jumlah variabel (kolom) :", ncol(df_raw), "\n")
## Jumlah variabel (kolom) : 110

Dataset ini memuat informasi mengenai pemain dari berbagai liga di seluruh dunia, mencakup:

  • Variabel identitas pemain: nama, usia, kebangsaan, klub, dan posisi bermain.
  • Variabel performa umum: nilai overall, potential, nilai pasar (value_eur), dan gaji (wage_eur).
  • Variabel atribut skill: mencakup kemampuan teknis seperti passing, dribbling, shooting; kemampuan fisik seperti pace, stamina, strength; serta kemampuan mental seperti vision, composure, dan positioning.
  • Variabel khusus kiper: goalkeeping_diving, goalkeeping_handling, dan sejenisnya.

1.3 Tujuan Analisis

Tujuan dari analisis ini adalah sebagai berikut:

  1. Melakukan pembersihan data (data cleaning) agar dataset siap digunakan untuk analisis multivariat.
  2. Mengeksplorasi karakteristik dasar data melalui statistik deskriptif dan visualisasi.
  3. Mengidentifikasi indikasi multikolinearitas antar variabel skill pemain lapangan.
  4. Menjadi dasar penggunaan Principal Component Analysis (PCA) pada tahap analisis berikutnya.

2 Exploratory Data Analysis (EDA)

2.1 Data Cleaning

2.1.1 Impor dan Pemeriksaan Struktur Data

# Memeriksa struktur data
glimpse(df_raw)
## Rows: 18,405
## Columns: 110
## $ player_id                      <int> 252371, 239053, 212622, 235212, 224232,…
## $ player_url                     <chr> "/player/252371/jude-bellingham/260004/…
## $ fifa_version                   <int> 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,…
## $ fifa_update                    <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, …
## $ fifa_update_date               <chr> "2025-09-19", "2025-09-19", "2025-09-19…
## $ short_name                     <chr> "J. Bellingham", "F. Valverde", "J. Kim…
## $ long_name                      <chr> "Jude Victor William Bellingham", "Fede…
## $ player_positions               <chr> "CAM, CM", "CM, CDM, RB", "CDM, RB, CM"…
## $ overall                        <int> 90, 89, 89, 89, 87, 86, 85, 87, 90, 85,…
## $ potential                      <int> 94, 90, 89, 90, 87, 86, 85, 88, 90, 85,…
## $ value_eur                      <int> 174500000, 120500000, 86000000, 1110000…
## $ wage_eur                       <int> 320000, 340000, 140000, 170000, 69000, …
## $ age                            <int> 22, 26, 30, 26, 28, 31, 27, 26, 29, 34,…
## $ dob                            <chr> "2003-06-29", "1998-07-22", "1995-02-08…
## $ height_cm                      <int> 186, 182, 177, 181, 175, 178, 175, 176,…
## $ weight_kg                      <int> 75, 74, 75, 73, 68, 69, 76, 72, 82, 67,…
## $ league_id                      <int> 53, 53, 19, 16, 31, 31, 31, 13, 13, 53,…
## $ league_name                    <chr> "La Liga", "La Liga", "Bundesliga", "Li…
## $ league_level                   <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ club_team_id                   <int> 243, 243, 21, 73, 44, 44, 44, 9, 10, 24…
## $ club_name                      <chr> "Real Madrid", "Real Madrid", "FC Bayer…
## $ club_position                  <chr> "CAM", "RDM", "RDM", "RB", "RCM", "CDM"…
## $ club_jersey_number             <int> 5, 8, 6, 2, 23, 20, 32, 10, 16, 7, 19, …
## $ club_loaned_from               <chr> "", "", "", "", "", "", "", "", "", "",…
## $ club_joined_date               <chr> "2023-07-01", "2016-07-22", "2015-07-01…
## $ club_contract_valid_until_year <int> 2029, 2029, 2029, 2029, 2029, 2027, 202…
## $ nationality_id                 <int> 14, 60, 21, 129, 27, 48, 27, 52, 45, 18…
## $ nationality_name               <chr> "England", "Uruguay", "Germany", "Moroc…
## $ nation_team_id                 <int> 1318, NA, 1337, 111111, 1343, NA, 1343,…
## $ nation_position                <chr> "CAM", "", "RCM", "RB", "RCM", "", "LB"…
## $ nation_jersey_number           <int> 10, NA, 6, 2, 18, NA, 3, 20, 16, NA, 22…
## $ preferred_foot                 <chr> "Right", "Right", "Right", "Right", "Ri…
## $ weak_foot                      <int> 4, 4, 4, 4, 4, 5, 4, 3, 4, 3, 3, 4, 4, …
## $ skill_moves                    <int> 4, 3, 3, 4, 3, 4, 3, 3, 3, 4, 4, 4, 4, …
## $ international_reputation       <int> 5, 4, 4, 4, 4, 4, 3, 4, 5, 4, 3, 4, 4, …
## $ work_rate                      <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ body_type                      <chr> "Normal (170-185)", "Unique", "Normal (…
## $ real_face                      <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes…
## $ release_clause_eur             <int> 370800000, 256100000, 141900000, 213700…
## $ player_tags                    <chr> "#Dribbler, #Playmaker , #Clinical fini…
## $ player_traits                  <chr> "Relentless +, Low Driven Shot, Gamecha…
## $ pace                           <int> 80, 88, 72, 92, 80, 71, 80, 66, 65, 77,…
## $ shooting                       <int> 86, 84, 74, 79, 78, 81, 78, 82, 80, 86,…
## $ passing                        <int> 83, 84, 89, 82, 84, 87, 84, 85, 86, 85,…
## $ dribbling                      <int> 90, 84, 84, 83, 86, 82, 82, 85, 84, 88,…
## $ defending                      <int> 78, 83, 83, 82, 81, 81, 79, 78, 86, 59,…
## $ physic                         <int> 85, 85, 79, 79, 76, 73, 77, 76, 85, 73,…
## $ attacking_crossing             <int> 66, 78, 92, 85, 79, 78, 87, 79, 76, 82,…
## $ attacking_finishing            <int> 88, 80, 68, 80, 77, 75, 74, 79, 74, 86,…
## $ attacking_heading_accuracy     <int> 75, 63, 72, 71, 60, 65, 69, 65, 81, 79,…
## $ attacking_short_passing        <int> 90, 88, 89, 86, 89, 90, 84, 88, 93, 86,…
## $ attacking_volleys              <int> 77, 78, 69, 74, 80, 78, 82, 77, 71, 86,…
## $ skill_dribbling                <int> 91, 84, 82, 82, 84, 78, 79, 84, 84, 86,…
## $ skill_curve                    <int> 73, 76, 85, 78, 79, 88, 88, 83, 86, 89,…
## $ skill_fk_accuracy              <int> 68, 69, 79, 80, 67, 85, 83, 82, 64, 85,…
## $ skill_long_passing             <int> 89, 88, 92, 73, 87, 89, 83, 87, 91, 83,…
## $ skill_ball_control             <int> 91, 88, 86, 85, 87, 87, 86, 86, 90, 90,…
## $ movement_acceleration          <int> 81, 84, 75, 89, 82, 74, 83, 68, 65, 80,…
## $ movement_sprint_speed          <int> 80, 92, 70, 95, 78, 68, 78, 64, 65, 75,…
## $ movement_agility               <int> 83, 77, 83, 81, 91, 83, 84, 82, 66, 88,…
## $ movement_reactions             <int> 91, 89, 89, 90, 91, 87, 83, 89, 93, 87,…
## $ movement_balance               <int> 83, 68, 84, 78, 88, 77, 81, 86, 67, 85,…
## $ power_shot_power               <int> 86, 91, 78, 82, 80, 87, 81, 88, 92, 85,…
## $ power_jumping                  <int> 85, 82, 77, 84, 75, 73, 81, 72, 83, 84,…
## $ power_stamina                  <int> 94, 93, 92, 95, 89, 81, 84, 87, 91, 77,…
## $ power_strength                 <int> 80, 82, 69, 72, 66, 65, 72, 69, 83, 70,…
## $ power_long_shots               <int> 87, 91, 83, 77, 79, 87, 84, 85, 89, 86,…
## $ mentality_aggression           <int> 85, 81, 89, 77, 87, 83, 81, 83, 85, 74,…
## $ mentality_interceptions        <int> 82, 86, 85, 85, 85, 82, 80, 80, 84, 59,…
## $ mentality_positioning          <int> 91, 86, 78, 84, 84, 73, 83, 78, 76, 87,…
## $ mentality_vision               <int> 90, 86, 86, 78, 85, 89, 80, 86, 84, 86,…
## $ mentality_penalties            <int> 74, 59, 71, 68, 73, 92, 71, 86, 62, 79,…
## $ mentality_composure            <int> 90, 84, 86, 84, 88, 85, 78, 86, 93, 88,…
## $ defending_marking_awareness    <int> 77, 82, 82, 82, 80, 81, 81, 78, 88, 45,…
## $ defending_standing_tackle      <int> 79, 87, 86, 85, 85, 85, 81, 83, 87, 63,…
## $ defending_sliding_tackle       <int> 77, 86, 85, 79, 80, 80, 79, 74, 82, 64,…
## $ goalkeeping_diving             <int> 14, 6, 8, 10, 11, 9, 9, 7, 10, 14, 12, …
## $ goalkeeping_handling           <int> 11, 10, 15, 8, 5, 14, 8, 10, 10, 8, 10,…
## $ goalkeeping_kicking            <int> 10, 6, 7, 14, 13, 11, 12, 14, 7, 14, 7,…
## $ goalkeeping_positioning        <int> 5, 15, 15, 6, 14, 6, 7, 15, 14, 13, 7, …
## $ goalkeeping_reflexes           <int> 8, 8, 15, 8, 11, 10, 7, 10, 8, 14, 7, 1…
## $ goalkeeping_speed              <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ ls                             <chr> "86+3", "84+3", "77+3", "82+3", "80+3",…
## $ st                             <chr> "86+3", "84+3", "77+3", "82+3", "80+3",…
## $ rs                             <chr> "86+3", "84+3", "77+3", "82+3", "80+3",…
## $ lw                             <chr> "87+0", "85+0", "82+0", "84+0", "84+0",…
## $ lf                             <chr> "89+0", "86+0", "81+0", "84+0", "84+0",…
## $ cf                             <chr> "89+0", "86+0", "81+0", "84+0", "84+0",…
## $ rf                             <chr> "89+0", "86+0", "81+0", "84+0", "84+0",…
## $ rw                             <chr> "87+0", "85+0", "82+0", "84+0", "84+0",…
## $ lam                            <chr> "89+3", "86+3", "83+3", "83+3", "85+2",…
## $ cam                            <chr> "89+3", "86+3", "83+3", "83+3", "85+2",…
## $ ram                            <chr> "89+3", "86+3", "83+3", "83+3", "85+2",…
## $ lm                             <chr> "87+3", "86+3", "84+3", "85+3", "84+3",…
## $ lcm                            <chr> "89+3", "88+2", "87+2", "83+3", "86+1",…
## $ cm                             <chr> "89+3", "88+2", "87+2", "83+3", "86+1",…
## $ rcm                            <chr> "89+3", "88+2", "87+2", "83+3", "86+1",…
## $ rm                             <chr> "87+3", "86+3", "84+3", "85+3", "84+3",…
## $ lwb                            <chr> "83+3", "86+3", "86+3", "86+3", "84+3",…
## $ ldm                            <chr> "85+3", "87+3", "87+2", "83+3", "85+2",…
## $ cdm                            <chr> "85+3", "87+3", "87+2", "83+3", "85+2",…
## $ rdm                            <chr> "85+3", "87+3", "87+2", "83+3", "85+2",…
## $ rwb                            <chr> "83+3", "86+3", "86+3", "86+3", "84+3",…
## $ lb                             <chr> "82+3", "86+3", "85+3", "86+3", "83+3",…
## $ lcb                            <chr> "81+3", "83+3", "82+3", "81+3", "80+3",…
## $ cb                             <chr> "81+3", "83+3", "82+3", "81+3", "80+3",…
## $ rcb                            <chr> "81+3", "83+3", "82+3", "81+3", "80+3",…
## $ rb                             <chr> "82+3", "86+3", "85+3", "86+3", "83+3",…
## $ gk                             <chr> "18+3", "18+3", "21+3", "17+3", "19+3",…
## $ player_face_url                <chr> "https://cdn.sofifa.net/players/252/371…
cat("Dimensi data sebelum pembersihan:", nrow(df_raw), "baris x", ncol(df_raw), "kolom\n")
## Dimensi data sebelum pembersihan: 18405 baris x 110 kolom

2.1.2 Penghapusan Pemain Posisi Kiper (GK)

Pada dataset FC 26, pemain dengan posisi Goalkeeper (GK) memiliki profil atribut yang secara fundamental berbeda dari pemain lapangan. Atribut utama kiper—seperti goalkeeping_diving, goalkeeping_handling, goalkeeping_reflexes, dan goalkeeping_positioning—tidak relevan bagi pemain lapangan. Sebaliknya, atribut teknis seperti dribbling, passing, dan shooting pada kiper memiliki nilai yang sangat rendah dan tidak representatif. Keberadaan data kiper dapat mengakibatkan distorsi pada struktur korelasi antar variabel skill serta memengaruhi validitas komponen utama yang dihasilkan oleh PCA. Oleh karena itu, seluruh pemain dengan posisi GK dihapus dari dataset agar analisis lebih homogen dan representatif untuk pemain lapangan.

# Menghapus pemain kiper (GK)
df_field <- df_raw %>%
  filter(!grepl("GK", player_positions))

cat("Jumlah pemain setelah penghapusan GK:", nrow(df_field), "\n")
## Jumlah pemain setelah penghapusan GK: 16343

2.1.3 Pemilihan Variabel Skill Relevan

Untuk keperluan analisis multivariat, dipilih variabel-variabel atribut skill teknis dan fisik pemain lapangan yang relevan. Variabel identitas, administratif, dan atribut kiper dikeluarkan dari analisis.

# Memilih variabel skill yang relevan untuk analisis multivariat
variabel_skill <- c(
  "pace", "shooting", "passing", "dribbling", "defending", "physic",
  "attacking_crossing", "attacking_finishing", "attacking_heading_accuracy",
  "attacking_short_passing", "attacking_volleys",
  "skill_dribbling", "skill_curve", "skill_fk_accuracy",
  "skill_long_passing", "skill_ball_control",
  "movement_acceleration", "movement_sprint_speed", "movement_agility",
  "movement_reactions", "movement_balance",
  "power_shot_power", "power_jumping", "power_stamina",
  "power_strength", "power_long_shots",
  "mentality_aggression", "mentality_interceptions",
  "mentality_positioning", "mentality_vision",
  "mentality_penalties", "mentality_composure",
  "defending_marking_awareness", "defending_standing_tackle",
  "defending_sliding_tackle"
)

df_skill <- df_field %>%
  select(short_name, player_positions, overall, all_of(variabel_skill))

cat("Dimensi data setelah pemilihan variabel:\n")
## Dimensi data setelah pemilihan variabel:
cat("  Baris  :", nrow(df_skill), "\n")
##   Baris  : 16343
cat("  Kolom  :", ncol(df_skill), "\n")
##   Kolom  : 38

Ringkasan dimensi data sebelum dan sesudah pembersihan:

tabel_dim <- data.frame(
  Tahap     = c("Sebelum Pembersihan", "Setelah Hapus GK", "Setelah Pilih Variabel"),
  Baris     = c(nrow(df_raw), nrow(df_field), nrow(df_skill)),
  Kolom     = c(ncol(df_raw), ncol(df_field), ncol(df_skill))
)

kable(tabel_dim, caption = "Ringkasan Dimensi Data pada Setiap Tahap Pembersihan")
Ringkasan Dimensi Data pada Setiap Tahap Pembersihan
Tahap Baris Kolom
Sebelum Pembersihan 18405 110
Setelah Hapus GK 16343 110
Setelah Pilih Variabel 16343 38

2.2 Pemeriksaan Missing Value

# Menghitung missing value per variabel skill
df_num <- df_skill %>% select(all_of(variabel_skill))

mv_per_var <- df_num %>%
  summarise(across(everything(), ~sum(is.na(.)))) %>%
  pivot_longer(everything(), names_to = "Variabel", values_to = "Jumlah_NA") %>%
  arrange(desc(Jumlah_NA))

# Total missing value
total_mv <- sum(is.na(df_num))
cat("Total missing value pada variabel skill:", total_mv, "\n")
## Total missing value pada variabel skill: 0
# Menampilkan variabel dengan missing value > 0
mv_ada <- mv_per_var %>% filter(Jumlah_NA > 0)

if (nrow(mv_ada) > 0) {
  kable(mv_ada, caption = "Variabel dengan Missing Value")
} else {
  cat("Tidak terdapat missing value pada seluruh variabel skill yang dipilih.\n")
}
## Tidak terdapat missing value pada seluruh variabel skill yang dipilih.

Interpretasi: Apabila terdapat missing value, perlu dilakukan penanganan lebih lanjut seperti imputasi atau penghapusan baris sebelum analisis multivariat dilanjutkan. Apabila tidak terdapat missing value, maka data siap untuk tahap analisis berikutnya tanpa perlakuan tambahan.

# Menghapus baris dengan missing value (jika ada)
df_clean <- df_skill %>%
  drop_na(all_of(variabel_skill))

cat("Dimensi data setelah penghapusan missing value:",
    nrow(df_clean), "baris x", ncol(df_clean), "kolom\n")
## Dimensi data setelah penghapusan missing value: 16343 baris x 38 kolom

2.3 Statistik Deskriptif

# Menghitung statistik deskriptif
df_num_clean <- df_clean %>% select(all_of(variabel_skill))

stat_desk <- df_num_clean %>%
  summarise(across(everything(), list(
    Mean   = ~round(mean(., na.rm = TRUE), 2),
    Median = ~round(median(., na.rm = TRUE), 2),
    SD     = ~round(sd(., na.rm = TRUE), 2),
    Min    = ~min(., na.rm = TRUE),
    Maks   = ~max(., na.rm = TRUE)
  ))) %>%
  pivot_longer(everything(),
               names_to  = c("Variabel", ".value"),
               names_sep = "_(?=[^_]+$)") %>%
  rename(`Std. Deviasi` = SD, Minimum = Min, Maksimum = Maks)

kable(stat_desk,
      caption = "Statistik Deskriptif Variabel Skill Pemain Lapangan FC 26",
      align   = "lrrrrr")
Statistik Deskriptif Variabel Skill Pemain Lapangan FC 26
Variabel Mean Median Std. Deviasi Minimum Maksimum
pace 68.37 69 10.52 30 97
shooting 52.81 55 13.94 21 92
passing 57.61 58 9.91 25 92
dribbling 62.88 64 9.38 22 93
defending 51.95 57 16.20 15 90
physic 64.76 66 9.75 32 91
attacking_crossing 53.64 55 13.43 20 93
attacking_finishing 51.33 55 15.97 15 94
attacking_heading_accuracy 56.64 57 11.37 20 93
attacking_short_passing 63.16 64 9.11 25 93
attacking_volleys 46.45 46 14.20 15 92
skill_dribbling 61.41 63 11.40 17 94
skill_curve 51.91 52 14.23 15 93
skill_fk_accuracy 45.93 44 13.89 15 94
skill_long_passing 57.21 58 11.43 20 93
skill_ball_control 63.77 64 9.21 20 94
movement_acceleration 68.27 69 11.07 27 97
movement_sprint_speed 68.43 69 10.86 30 97
movement_agility 66.29 67 12.03 25 94
movement_reactions 62.38 62 8.49 31 94
movement_balance 66.74 68 11.85 29 95
power_shot_power 58.84 60 12.87 20 94
power_jumping 66.94 68 11.63 27 95
power_stamina 66.97 67 11.21 27 95
power_strength 65.43 66 12.33 24 95
power_long_shots 51.22 54 15.47 15 91
mentality_aggression 59.67 61 13.02 24 94
mentality_interceptions 50.88 57 18.34 10 91
mentality_positioning 55.94 59 14.23 15 95
mentality_vision 56.42 58 12.46 22 92
mentality_penalties 51.04 50 12.06 20 93
mentality_composure 60.13 60 10.02 30 93
defending_marking_awareness 50.57 56 17.70 10 91
defending_standing_tackle 52.85 59 17.98 10 91
defending_sliding_tackle 50.40 56 17.95 10 89

Interpretasi: Berdasarkan tabel di atas, dapat diamati bahwa terdapat variasi yang cukup besar antar variabel skill. Nilai rata-rata dan median yang berdekatan pada sebagian besar variabel mengindikasikan distribusi yang relatif simetris. Namun, nilai standar deviasi yang relatif besar pada beberapa atribut menunjukkan adanya heterogenitas kemampuan pemain yang signifikan dalam dataset. Perbedaan skala antar variabel yang tidak terlalu ekstrem mengindikasikan bahwa normalisasi data perlu dipertimbangkan sebelum penerapan PCA.

2.4 Deteksi Outlier

Deteksi outlier dilakukan secara visual menggunakan boxplot untuk beberapa atribut skill utama yang merepresentasikan dimensi teknis, fisik, dan mental pemain.

# Memilih atribut utama untuk visualisasi outlier
atribut_utama <- c(
  "skill_ball_control", "attacking_short_passing", "skill_long_passing",
  "mentality_vision", "skill_dribbling", "movement_acceleration",
  "power_stamina", "power_strength", "defending_standing_tackle",
  "mentality_composure"
)

df_plot <- df_clean %>%
  select(all_of(atribut_utama)) %>%
  pivot_longer(everything(), names_to = "Atribut", values_to = "Nilai")

ggplot(df_plot, aes(x = Atribut, y = Nilai)) +
  geom_boxplot(fill = "steelblue", alpha = 0.6, outlier.colour = "red",
               outlier.size = 1) +
  labs(
    title   = "Boxplot Atribut Skill Utama Pemain Lapangan FC 26",
    subtitle = "Titik merah menunjukkan nilai yang teridentifikasi sebagai outlier",
    x       = "Atribut Skill",
    y       = "Nilai"
  ) +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 9))

Interpretasi: Visualisasi boxplot di atas menunjukkan adanya sejumlah nilai ekstrem (outlier) pada beberapa atribut skill. Outlier yang muncul umumnya berasal dari pemain-pemain elit dengan kemampuan jauh di atas rata-rata, maupun dari pemain muda atau pemain dengan spesialisasi posisi tertentu yang memiliki profil atribut tidak seimbang. Keberadaan outlier perlu diperhatikan karena dapat memengaruhi struktur kovarians data dan pada akhirnya memengaruhi arah serta interpretasi komponen utama yang dihasilkan oleh PCA. Oleh karena itu, evaluasi lebih lanjut terhadap outlier diperlukan sebelum penerapan analisis multivariat lanjutan.

2.5 Analisis Korelasi

2.5.1 Tabel Korelasi

# Menghitung matriks korelasi
mat_kor <- cor(df_num_clean, use = "complete.obs", method = "pearson")

# Menampilkan sebagian tabel korelasi (10 variabel pertama) agar mudah dibaca
kable(
  round(mat_kor[1:10, 1:10], 3),
  caption = "Matriks Korelasi Pearson (10 Variabel Pertama)"
)
Matriks Korelasi Pearson (10 Variabel Pertama)
pace shooting passing dribbling defending physic attacking_crossing attacking_finishing attacking_heading_accuracy attacking_short_passing
pace 1.000 0.355 0.294 0.505 -0.255 -0.122 0.424 0.370 -0.218 0.150
shooting 0.355 1.000 0.667 0.773 -0.384 0.018 0.540 0.974 0.045 0.502
passing 0.294 0.667 1.000 0.862 0.218 0.191 0.834 0.584 0.070 0.897
dribbling 0.505 0.773 0.862 1.000 -0.061 0.064 0.752 0.727 -0.001 0.737
defending -0.255 -0.384 0.218 -0.061 1.000 0.525 0.116 -0.467 0.340 0.366
physic -0.122 0.018 0.191 0.064 0.525 1.000 0.023 -0.056 0.683 0.350
attacking_crossing 0.424 0.540 0.834 0.752 0.116 0.023 1.000 0.479 -0.106 0.590
attacking_finishing 0.370 0.974 0.584 0.727 -0.467 -0.056 0.479 1.000 -0.006 0.419
attacking_heading_accuracy -0.218 0.045 0.070 -0.001 0.340 0.683 -0.106 -0.006 1.000 0.270
attacking_short_passing 0.150 0.502 0.897 0.737 0.366 0.350 0.590 0.419 0.270 1.000

2.5.2 Heatmap Korelasi

corrplot(
  mat_kor,
  method  = "color",
  type    = "upper",
  order   = "hclust",
  tl.cex  = 0.65,
  tl.col  = "black",
  addCoef.col = NULL,
  col     = colorRampPalette(c("blue", "white", "red"))(200),
  title   = "Heatmap Korelasi Antar Variabel Skill Pemain FC 26",
  mar     = c(0, 0, 1.5, 0)
)

2.6 Identifikasi Multikolinearitas

Berdasarkan hasil analisis korelasi pada Sub-bab 2.5, teridentifikasi adanya korelasi yang sangat tinggi di antara banyak variabel skill pemain lapangan. Sebagai contoh, atribut short passing (attacking_short_passing) menunjukkan korelasi yang sangat kuat dengan ball control (skill_ball_control), vision (mentality_vision), long passing (skill_long_passing), dan dribbling (skill_dribbling). Kondisi serupa juga dijumpai pada kelompok atribut teknis lainnya, di mana pasangan variabel seperti skill_dribbling dengan movement_agility, serta power_shot_power dengan attacking_finishing, memiliki nilai korelasi yang tinggi.

# Mengidentifikasi pasangan variabel dengan korelasi sangat tinggi (|r| > 0.80)
mat_kor_df <- as.data.frame(as.table(mat_kor)) %>%
  rename(Var1 = Var1, Var2 = Var2, Korelasi = Freq) %>%
  filter(as.character(Var1) < as.character(Var2)) %>%
  filter(abs(Korelasi) > 0.80) %>%
  arrange(desc(abs(Korelasi)))

kable(
  mat_kor_df %>% mutate(Korelasi = round(Korelasi, 3)),
  caption = "Pasangan Variabel Skill dengan Korelasi Sangat Tinggi (|r| > 0.80)"
)
Pasangan Variabel Skill dengan Korelasi Sangat Tinggi (|r| > 0.80)
Var1 Var2 Korelasi
defending defending_standing_tackle 0.981
defending defending_marking_awareness 0.978
attacking_finishing shooting 0.974
defending mentality_interceptions 0.974
dribbling skill_dribbling 0.972
defending_sliding_tackle defending_standing_tackle 0.972
defending defending_sliding_tackle 0.970
movement_sprint_speed pace 0.967
movement_acceleration pace 0.952
defending_standing_tackle mentality_interceptions 0.949
power_long_shots shooting 0.944
defending_marking_awareness mentality_interceptions 0.940
defending_marking_awareness defending_standing_tackle 0.939
defending_sliding_tackle mentality_interceptions 0.936
defending_marking_awareness defending_sliding_tackle 0.934
dribbling skill_ball_control 0.925
physic power_strength 0.904
attacking_short_passing passing 0.897
mentality_vision passing 0.894
attacking_volleys shooting 0.886
power_shot_power shooting 0.883
mentality_positioning shooting 0.878
attacking_short_passing skill_long_passing 0.875
attacking_finishing power_long_shots 0.873
dribbling passing 0.862
passing skill_ball_control 0.860
attacking_finishing mentality_positioning 0.859
passing skill_long_passing 0.854
skill_ball_control skill_dribbling 0.852
power_long_shots power_shot_power 0.851
attacking_finishing attacking_volleys 0.846
movement_acceleration movement_sprint_speed 0.844
dribbling mentality_vision 0.838
physic power_jumping 0.836
attacking_crossing passing 0.834
attacking_short_passing skill_ball_control 0.828
passing skill_curve 0.825
mentality_positioning power_long_shots 0.823
power_jumping power_strength 0.820
attacking_volleys power_long_shots 0.818
attacking_heading_accuracy power_jumping 0.817
mentality_penalties shooting 0.814
mentality_positioning skill_dribbling 0.813
dribbling mentality_positioning 0.809
mentality_vision skill_dribbling 0.808
passing skill_dribbling 0.806

Keberadaan korelasi yang sangat tinggi antar variabel ini secara statistik mengindikasikan adanya multikolinearitas yang kuat dalam dataset. Multikolinearitas menyebabkan informasi yang dikandung oleh suatu variabel sebagian besar sudah tercakup dalam variabel lainnya, sehingga terjadi redundansi informasi yang signifikan. Dalam konteks analisis regresi, multikolinearitas dapat menyebabkan estimasi koefisien menjadi tidak stabil. Dalam konteks analisis eksplorasi seperti yang dilakukan pada laporan ini, multikolinearitas menjadi justifikasi utama penerapan metode reduksi dimensi.

Principal Component Analysis (PCA) merupakan metode yang secara khusus dirancang untuk menangani kondisi multikolinearitas dengan cara mentransformasi variabel-variabel asli yang saling berkorelasi menjadi komponen-komponen utama yang saling ortogonal (tidak berkorelasi). Dengan demikian, redundansi informasi dapat dieliminasi, dimensi data dapat dikurangi secara signifikan, dan struktur laten dalam data dapat diungkap dengan lebih jelas.


3 Feature Engineering

Tahap feature engineering dilakukan untuk membentuk variabel turunan yang memiliki makna substantif dalam konteks evaluasi performa pemain sepak bola. Variabel baru tidak hanya dibuat berdasarkan operasi matematis, tetapi juga berdasarkan logika permainan, kebutuhan scouting, dan karakteristik atribut pemain dalam dataset FC 26. Pada bagian ini, tiga variabel baru dibentuk, yaitu Is_Wonderkid, Goal_Contribution_Potential, dan Physical_Dominance.

# Membentuk kembali dataset untuk feature engineering
# karena variabel age dan potential tidak termasuk dalam df_clean pada tahap EDA.
df_fe <- df_field %>%
  select(
    short_name, player_positions, age, potential, overall,
    all_of(variabel_skill)
  ) %>%
  drop_na(age, potential, overall, all_of(variabel_skill)) %>%
  mutate(
    # 1. Pemain muda dengan potensi tinggi
    Is_Wonderkid = ifelse(age <= 21 & potential >= 80, 1, 0),

    # 2. Potensi kontribusi gol dari atribut menyerang
    Goal_Contribution_Potential = rowMeans(
      select(
        ., shooting, attacking_finishing, attacking_volleys,
        power_shot_power, power_long_shots,
        mentality_positioning, mentality_penalties
      ),
      na.rm = TRUE
    ),

    # 3. Dominasi fisik dari atribut kekuatan, stamina, kecepatan, dan kelincahan
    Physical_Dominance = rowMeans(
      select(
        ., physic, power_strength, power_stamina, power_jumping,
        movement_acceleration, movement_sprint_speed,
        movement_agility, movement_balance
      ),
      na.rm = TRUE
    )
  )

# Menampilkan contoh hasil feature engineering
kable(
  head(
    df_fe %>%
      select(
        short_name, player_positions, age, potential, overall,
        Is_Wonderkid, Goal_Contribution_Potential, Physical_Dominance
      ),
    10
  ),
  digits = 2,
  caption = "Contoh Hasil Pembentukan Variabel Baru"
)
Contoh Hasil Pembentukan Variabel Baru
short_name player_positions age potential overall Is_Wonderkid Goal_Contribution_Potential Physical_Dominance
J. Bellingham CAM, CM 22 94 90 0 84.14 83.88
F. Valverde CM, CDM, RB 26 90 89 0 81.29 82.88
J. Kimmich CDM, RB, CM 30 89 89 0 74.43 78.62
A. Hakimi RB, RM 26 90 89 0 77.71 84.12
N. Barella CM 28 87 87 0 78.71 80.62
H. Çalhanoğlu CDM, CM 31 86 86 0 81.86 74.25
F. Dimarco LB, LM 27 85 85 0 79.00 80.00
A. Mac Allister CM, CDM 26 88 87 0 82.14 75.50
Rodri CDM, CM 29 90 90 0 77.71 75.62
A. Griezmann ST, LM, CAM 34 85 85 0 85.00 79.00

3.1 Alasan Substantif Pembentukan Variabel

Pertama, variabel Is_Wonderkid dibuat menggunakan teknik binning dengan ketentuan pemain berusia maksimal 21 tahun dan memiliki nilai potential minimal 80 diberi nilai 1, sedangkan pemain lain diberi nilai 0. Secara substantif, variabel ini berguna untuk mengidentifikasi pemain muda yang memiliki prospek perkembangan tinggi. Dalam konteks sepak bola modern, pemain seperti ini sering menjadi fokus scouting karena dapat memiliki nilai strategis jangka panjang bagi klub.

Kedua, variabel Goal_Contribution_Potential dibentuk dari rata-rata beberapa atribut menyerang, yaitu shooting, attacking_finishing, attacking_volleys, power_shot_power, power_long_shots, mentality_positioning, dan mentality_penalties. Variabel ini dibuat karena kontribusi gol seorang pemain tidak hanya ditentukan oleh satu atribut, tetapi merupakan kombinasi dari kemampuan menyelesaikan peluang, kekuatan tembakan, kemampuan melakukan tembakan jarak jauh, serta kecerdasan posisi di area menyerang.

Ketiga, variabel Physical_Dominance dibentuk dari rata-rata atribut fisik seperti physic, power_strength, power_stamina, power_jumping, movement_acceleration, movement_sprint_speed, movement_agility, dan movement_balance. Variabel ini merepresentasikan dominasi fisik pemain secara lebih menyeluruh. Pemain dengan nilai fisik tinggi umumnya lebih mampu memenangkan duel, menjaga intensitas permainan, bergerak cepat, dan mempertahankan keseimbangan dalam situasi tekanan lawan.

3.2 Ringkasan Statistik Variabel Baru

fitur_baru <- c("Is_Wonderkid", "Goal_Contribution_Potential", "Physical_Dominance")

stat_fitur_baru <- df_fe %>%
  select(all_of(fitur_baru)) %>%
  summarise(across(everything(), list(
    Mean   = ~round(mean(., na.rm = TRUE), 2),
    Median = ~round(median(., na.rm = TRUE), 2),
    SD     = ~round(sd(., na.rm = TRUE), 2),
    Min    = ~round(min(., na.rm = TRUE), 2),
    Maks   = ~round(max(., na.rm = TRUE), 2)
  ))) %>%
  pivot_longer(
    everything(),
    names_to = c("Variabel", ".value"),
    names_sep = "_(?=[^_]+$)"
  ) %>%
  rename(`Std. Deviasi` = SD, Minimum = Min, Maksimum = Maks)

kable(
  stat_fitur_baru,
  caption = "Statistik Deskriptif Variabel Hasil Feature Engineering",
  align = "lrrrrr"
)
Statistik Deskriptif Variabel Hasil Feature Engineering
Variabel Mean Median Std. Deviasi Minimum Maksimum
Is_Wonderkid 0.04 0.00 0.20 0.00 1.00
Goal_Contribution_Potential 52.52 54.14 13.00 21.71 91.57
Physical_Dominance 66.73 67.00 6.47 39.50 89.50
df_fe %>%
  select(Goal_Contribution_Potential, Physical_Dominance) %>%
  pivot_longer(everything(), names_to = "Variabel", values_to = "Nilai") %>%
  ggplot(aes(x = Nilai)) +
  geom_histogram(bins = 30, fill = "steelblue", color = "white", alpha = 0.8) +
  facet_wrap(~ Variabel, scales = "free") +
  labs(
    title = "Distribusi Variabel Baru Hasil Feature Engineering",
    x = "Nilai",
    y = "Frekuensi"
  ) +
  theme_bw()

Interpretasi: Variabel hasil feature engineering memberikan ringkasan informasi yang lebih mudah dibaca dibandingkan atribut tunggal. Goal_Contribution_Potential merangkum aspek kemampuan menyerang, sedangkan Physical_Dominance merangkum kekuatan fisik dan mobilitas pemain. Sementara itu, Is_Wonderkid memberikan penanda kategorikal bagi pemain muda dengan potensi tinggi. Ketiga variabel ini dapat digunakan sebagai kandidat prediktor tambahan dalam proses seleksi fitur terhadap nilai overall.


4 Feature Selection

Tahap feature selection dilakukan untuk mengidentifikasi atribut yang paling relevan terhadap nilai overall. Seleksi fitur penting dilakukan karena dataset memiliki banyak atribut yang saling berkorelasi. Jika seluruh variabel digunakan secara langsung, model dapat menjadi kurang efisien dan interpretasi menjadi sulit karena adanya redundansi informasi. Pada bagian ini digunakan dua pendekatan, yaitu filter method berbasis korelasi dan embedded method berbasis Random Forest Feature Importance.

4.1 Persiapan Data Seleksi Fitur

# Menggabungkan variabel skill asli dan variabel hasil feature engineering
predictor_vars <- c(variabel_skill, fitur_baru)

feature_selection_data <- df_fe %>%
  select(overall, all_of(predictor_vars)) %>%
  drop_na()

cat("Jumlah observasi untuk feature selection:", nrow(feature_selection_data), "\n")
## Jumlah observasi untuk feature selection: 16343
cat("Jumlah kandidat prediktor:", length(predictor_vars), "\n")
## Jumlah kandidat prediktor: 38

4.2 Metode 1: Filter Method Menggunakan Matriks Korelasi

Filter method dilakukan dengan memeriksa korelasi antarvariabel prediktor. Variabel yang memiliki korelasi absolut sangat tinggi dapat dianggap redundan karena membawa informasi yang hampir sama. Dalam analisis ini, batas korelasi tinggi ditetapkan pada |r| > 0,80. Untuk setiap pasangan variabel yang redundan, variabel yang korelasinya lebih rendah terhadap overall disarankan untuk dibuang.

# Matriks korelasi antar prediktor
cor_predictor <- cor(
  feature_selection_data %>% select(all_of(predictor_vars)),
  use = "complete.obs",
  method = "pearson"
)

# Korelasi setiap prediktor dengan target overall
cor_target <- cor(
  feature_selection_data %>% select(all_of(predictor_vars)),
  feature_selection_data$overall,
  use = "complete.obs",
  method = "pearson"
)[, 1]

# Visualisasi korelasi antar prediktor
corrplot(
  cor_predictor,
  method = "color",
  type = "upper",
  order = "hclust",
  tl.cex = 0.55,
  tl.col = "black",
  addCoef.col = NULL,
  col = colorRampPalette(c("blue", "white", "red"))(200),
  title = "Heatmap Korelasi Kandidat Prediktor",
  mar = c(0, 0, 1.5, 0)
)

# Mengubah matriks korelasi menjadi tabel pasangan variabel
high_corr_pairs <- as.data.frame(as.table(cor_predictor)) %>%
  rename(Var1 = Var1, Var2 = Var2, Korelasi = Freq) %>%
  filter(as.character(Var1) < as.character(Var2)) %>%
  filter(abs(Korelasi) > 0.80) %>%
  mutate(
    Korelasi = round(Korelasi, 3),
    Kor_Overall_Var1 = round(cor_target[as.character(Var1)], 3),
    Kor_Overall_Var2 = round(cor_target[as.character(Var2)], 3),
    Rekomendasi_Dibuang = ifelse(
      abs(cor_target[as.character(Var1)]) < abs(cor_target[as.character(Var2)]),
      as.character(Var1),
      as.character(Var2)
    )
  ) %>%
  arrange(desc(abs(Korelasi)))

if (nrow(high_corr_pairs) > 0) {
  kable(
    high_corr_pairs,
    caption = "Pasangan Variabel dengan Korelasi Tinggi dan Rekomendasi Penghapusan"
  )
} else {
  cat("Tidak terdapat pasangan variabel dengan korelasi absolut di atas 0,80.\n")
}
Pasangan Variabel dengan Korelasi Tinggi dan Rekomendasi Penghapusan
Var1 Var2 Korelasi Kor_Overall_Var1 Kor_Overall_Var2 Rekomendasi_Dibuang
Goal_Contribution_Potential shooting 0.993 0.496 0.478 shooting
defending defending_standing_tackle 0.981 0.366 0.318 defending_standing_tackle
defending defending_marking_awareness 0.978 0.366 0.354 defending_marking_awareness
attacking_finishing shooting 0.974 0.399 0.478 attacking_finishing
defending mentality_interceptions 0.974 0.366 0.343 mentality_interceptions
dribbling skill_dribbling 0.972 0.693 0.600 skill_dribbling
defending_sliding_tackle defending_standing_tackle 0.972 0.283 0.318 defending_sliding_tackle
defending defending_sliding_tackle 0.970 0.366 0.283 defending_sliding_tackle
movement_sprint_speed pace 0.967 0.231 0.236 movement_sprint_speed
attacking_finishing Goal_Contribution_Potential 0.954 0.399 0.496 attacking_finishing
movement_acceleration pace 0.952 0.220 0.236 movement_acceleration
defending_standing_tackle mentality_interceptions 0.949 0.318 0.343 defending_standing_tackle
power_long_shots shooting 0.944 0.476 0.478 power_long_shots
Goal_Contribution_Potential power_long_shots 0.941 0.496 0.476 power_long_shots
defending_marking_awareness mentality_interceptions 0.940 0.354 0.343 mentality_interceptions
defending_marking_awareness defending_standing_tackle 0.939 0.354 0.318 defending_standing_tackle
defending_sliding_tackle mentality_interceptions 0.936 0.283 0.343 defending_sliding_tackle
defending_marking_awareness defending_sliding_tackle 0.934 0.354 0.283 defending_sliding_tackle
dribbling skill_ball_control 0.925 0.693 0.793 dribbling
attacking_volleys Goal_Contribution_Potential 0.914 0.434 0.496 attacking_volleys
physic power_strength 0.904 0.555 0.363 power_strength
attacking_short_passing passing 0.897 0.812 0.735 passing
mentality_vision passing 0.894 0.576 0.735 mentality_vision
Goal_Contribution_Potential mentality_positioning 0.894 0.496 0.470 mentality_positioning
Goal_Contribution_Potential power_shot_power 0.887 0.496 0.562 Goal_Contribution_Potential
attacking_volleys shooting 0.886 0.434 0.478 attacking_volleys
power_shot_power shooting 0.883 0.562 0.478 shooting
mentality_positioning shooting 0.878 0.470 0.478 mentality_positioning
attacking_short_passing skill_long_passing 0.875 0.812 0.665 skill_long_passing
attacking_finishing power_long_shots 0.873 0.399 0.476 attacking_finishing
dribbling passing 0.862 0.693 0.735 dribbling
passing skill_ball_control 0.860 0.735 0.793 passing
attacking_finishing mentality_positioning 0.859 0.399 0.470 attacking_finishing
passing skill_long_passing 0.854 0.735 0.665 skill_long_passing
skill_ball_control skill_dribbling 0.852 0.793 0.600 skill_dribbling
power_long_shots power_shot_power 0.851 0.476 0.562 power_long_shots
Goal_Contribution_Potential mentality_penalties 0.847 0.496 0.389 mentality_penalties
attacking_finishing attacking_volleys 0.846 0.399 0.434 attacking_finishing
movement_acceleration movement_sprint_speed 0.844 0.220 0.231 movement_acceleration
dribbling mentality_vision 0.838 0.693 0.576 mentality_vision
physic power_jumping 0.836 0.555 0.589 physic
attacking_crossing passing 0.834 0.529 0.735 attacking_crossing
attacking_short_passing skill_ball_control 0.828 0.812 0.793 skill_ball_control
passing skill_curve 0.825 0.735 0.541 skill_curve
mentality_positioning power_long_shots 0.823 0.470 0.476 mentality_positioning
power_jumping power_strength 0.820 0.589 0.363 power_strength
attacking_volleys power_long_shots 0.818 0.434 0.476 attacking_volleys
attacking_heading_accuracy power_jumping 0.817 0.494 0.589 attacking_heading_accuracy
mentality_penalties shooting 0.814 0.389 0.478 mentality_penalties
mentality_positioning skill_dribbling 0.813 0.470 0.600 mentality_positioning
dribbling mentality_positioning 0.809 0.693 0.470 mentality_positioning
mentality_vision skill_dribbling 0.808 0.576 0.600 mentality_vision
passing skill_dribbling 0.806 0.735 0.600 skill_dribbling
# Daftar variabel redundan yang direkomendasikan untuk dibuang
redundant_vars <- unique(high_corr_pairs$Rekomendasi_Dibuang)
selected_filter_vars <- setdiff(predictor_vars, redundant_vars)

cat("Jumlah variabel yang direkomendasikan dibuang:", length(redundant_vars), "\n")
## Jumlah variabel yang direkomendasikan dibuang: 24
cat("Jumlah variabel yang dipertahankan setelah filter method:", length(selected_filter_vars), "\n")
## Jumlah variabel yang dipertahankan setelah filter method: 14
tabel_filter_selection <- data.frame(
  Kategori = c(
    rep("Dibuang karena redundan", length(redundant_vars)),
    rep("Dipertahankan", length(selected_filter_vars))
  ),
  Variabel = c(redundant_vars, selected_filter_vars)
)

kable(
  tabel_filter_selection,
  caption = "Hasil Seleksi Fitur dengan Filter Method"
)
Hasil Seleksi Fitur dengan Filter Method
Kategori Variabel
Dibuang karena redundan shooting
Dibuang karena redundan defending_standing_tackle
Dibuang karena redundan defending_marking_awareness
Dibuang karena redundan attacking_finishing
Dibuang karena redundan mentality_interceptions
Dibuang karena redundan skill_dribbling
Dibuang karena redundan defending_sliding_tackle
Dibuang karena redundan movement_sprint_speed
Dibuang karena redundan movement_acceleration
Dibuang karena redundan power_long_shots
Dibuang karena redundan dribbling
Dibuang karena redundan attacking_volleys
Dibuang karena redundan power_strength
Dibuang karena redundan passing
Dibuang karena redundan mentality_vision
Dibuang karena redundan mentality_positioning
Dibuang karena redundan Goal_Contribution_Potential
Dibuang karena redundan skill_long_passing
Dibuang karena redundan mentality_penalties
Dibuang karena redundan physic
Dibuang karena redundan attacking_crossing
Dibuang karena redundan skill_ball_control
Dibuang karena redundan skill_curve
Dibuang karena redundan attacking_heading_accuracy
Dipertahankan pace
Dipertahankan defending
Dipertahankan attacking_short_passing
Dipertahankan skill_fk_accuracy
Dipertahankan movement_agility
Dipertahankan movement_reactions
Dipertahankan movement_balance
Dipertahankan power_shot_power
Dipertahankan power_jumping
Dipertahankan power_stamina
Dipertahankan mentality_aggression
Dipertahankan mentality_composure
Dipertahankan Is_Wonderkid
Dipertahankan Physical_Dominance

Interpretasi: Berdasarkan filter method, variabel dengan korelasi sangat tinggi terhadap variabel lain dianggap memiliki informasi yang tumpang tindih. Oleh karena itu, salah satu variabel dari pasangan yang redundan dapat dipertimbangkan untuk dikeluarkan. Pemilihan variabel yang dibuang dilakukan dengan mempertahankan variabel yang memiliki korelasi lebih kuat terhadap overall, sehingga proses reduksi fitur tetap mempertimbangkan relevansi terhadap target analisis.

4.3 Metode 2: Embedded Method Menggunakan Random Forest Feature Importance

Metode kedua menggunakan Random Forest Feature Importance. Metode ini termasuk embedded method karena proses seleksi fitur dilakukan di dalam algoritma pemodelan. Random Forest menilai seberapa besar kontribusi setiap variabel dalam menurunkan kesalahan prediksi dan membentuk pemisahan data yang informatif. Variabel dengan nilai importance tinggi dapat dianggap lebih berpengaruh terhadap nilai overall.

if (!requireNamespace("randomForest", quietly = TRUE)) {
  stop("Paket randomForest belum terpasang. Jalankan install.packages('randomForest') terlebih dahulu.")
}

library(randomForest)

set.seed(123)

rf_model <- randomForest(
  overall ~ .,
  data = feature_selection_data,
  ntree = 500,
  importance = TRUE,
  na.action = na.omit
)

# Mengambil nilai feature importance
importance_matrix <- randomForest::importance(rf_model)

importance_df <- data.frame(
  Feature = rownames(importance_matrix),
  IncMSE = importance_matrix[, "%IncMSE"],
  IncNodePurity = importance_matrix[, "IncNodePurity"]
) %>%
  arrange(desc(IncMSE))

# Menampilkan 15 variabel paling penting
top_importance <- importance_df %>% slice_head(n = 15)

kable(
  top_importance,
  digits = 3,
  caption = "Lima Belas Variabel Terpenting Berdasarkan Random Forest"
)
Lima Belas Variabel Terpenting Berdasarkan Random Forest
Feature IncMSE IncNodePurity
Physical_Dominance Physical_Dominance 54.136 14603.373
pace pace 49.299 2201.234
movement_sprint_speed movement_sprint_speed 49.013 2178.513
attacking_finishing attacking_finishing 46.281 3191.004
attacking_crossing attacking_crossing 43.952 8466.834
shooting shooting 39.380 6749.997
power_stamina power_stamina 37.615 3414.506
movement_acceleration movement_acceleration 37.189 1440.661
defending defending 33.838 40837.330
defending_standing_tackle defending_standing_tackle 32.717 17879.866
power_jumping power_jumping 32.467 12088.305
power_strength power_strength 32.179 1357.240
Goal_Contribution_Potential Goal_Contribution_Potential 31.970 4463.513
movement_reactions movement_reactions 30.829 222077.569
physic physic 30.676 5027.931
ggplot(top_importance, aes(x = reorder(Feature, IncMSE), y = IncMSE)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(
    title = "Top 15 Feature Importance terhadap Overall Rating",
    subtitle = "Embedded Method: Random Forest",
    x = "Variabel",
    y = "Importance (%IncMSE)"
  ) +
  theme_bw()

# Variabel yang direkomendasikan berdasarkan Random Forest
# Diambil dari 10 variabel dengan importance tertinggi.
rf_selected_vars <- importance_df %>%
  slice_head(n = 10) %>%
  pull(Feature)

kable(
  data.frame(
    Peringkat = seq_along(rf_selected_vars),
    Variabel_Terpilih = rf_selected_vars
  ),
  caption = "Rekomendasi Variabel Terpilih Berdasarkan Random Forest"
)
Rekomendasi Variabel Terpilih Berdasarkan Random Forest
Peringkat Variabel_Terpilih
1 Physical_Dominance
2 pace
3 movement_sprint_speed
4 attacking_finishing
5 attacking_crossing
6 shooting
7 power_stamina
8 movement_acceleration
9 defending
10 defending_standing_tackle

Interpretasi: Hasil Random Forest Feature Importance menunjukkan variabel yang memiliki kontribusi paling besar dalam menjelaskan variasi nilai overall. Variabel yang berada pada peringkat atas dapat diprioritaskan sebagai prediktor utama karena memiliki pengaruh relatif lebih kuat terhadap performa umum pemain. Sebaliknya, variabel dengan nilai importance rendah dapat dipertimbangkan untuk tidak digunakan dalam model lanjutan, terutama apabila variabel tersebut juga terindikasi redundan pada tahap filter method.

4.4 Perbandingan Hasil Seleksi Fitur

# Membandingkan variabel yang dipertahankan oleh filter method dan RF top 10
comparison_selection <- data.frame(
  Variabel = unique(c(selected_filter_vars, rf_selected_vars)),
  Dipertahankan_Filter_Method = unique(c(selected_filter_vars, rf_selected_vars)) %in% selected_filter_vars,
  Masuk_Top10_Random_Forest = unique(c(selected_filter_vars, rf_selected_vars)) %in% rf_selected_vars
)

kable(
  comparison_selection,
  caption = "Perbandingan Hasil Filter Method dan Random Forest Feature Importance"
)
Perbandingan Hasil Filter Method dan Random Forest Feature Importance
Variabel Dipertahankan_Filter_Method Masuk_Top10_Random_Forest
pace TRUE TRUE
defending TRUE TRUE
attacking_short_passing TRUE FALSE
skill_fk_accuracy TRUE FALSE
movement_agility TRUE FALSE
movement_reactions TRUE FALSE
movement_balance TRUE FALSE
power_shot_power TRUE FALSE
power_jumping TRUE FALSE
power_stamina TRUE TRUE
mentality_aggression TRUE FALSE
mentality_composure TRUE FALSE
Is_Wonderkid TRUE FALSE
Physical_Dominance TRUE TRUE
movement_sprint_speed FALSE TRUE
attacking_finishing FALSE TRUE
attacking_crossing FALSE TRUE
shooting FALSE TRUE
movement_acceleration FALSE TRUE
defending_standing_tackle FALSE TRUE

Berdasarkan dua metode seleksi fitur, variabel yang ideal untuk diprioritaskan adalah variabel yang tidak redundan menurut filter method dan juga memiliki nilai penting tinggi menurut Random Forest. Kombinasi kedua metode ini membantu menghasilkan pemilihan fitur yang lebih seimbang. Filter method berfokus pada pengurangan redundansi antarvariabel, sedangkan Random Forest berfokus pada kontribusi prediktif variabel terhadap overall. Dengan demikian, hasil akhir seleksi fitur tidak hanya mempertimbangkan hubungan linear antarvariabel, tetapi juga mempertimbangkan kemampuan variabel dalam menjelaskan performa pemain secara model-based.

4.5 Kesimpulan Bagian Feature Engineering dan Feature Selection

Tahap feature engineering menghasilkan tiga variabel baru, yaitu Is_Wonderkid, Goal_Contribution_Potential, dan Physical_Dominance. Ketiga variabel tersebut memiliki dasar substantif yang relevan dengan analisis pemain sepak bola, karena masing-masing merepresentasikan potensi pemain muda, kemampuan kontribusi gol, dan dominasi fisik. Selanjutnya, tahap feature selection menunjukkan bahwa tidak semua atribut perlu digunakan secara bersamaan karena terdapat potensi redundansi informasi antarvariabel. Melalui filter method, variabel dengan korelasi sangat tinggi dapat diseleksi agar model lebih efisien. Sementara itu, Random Forest memberikan gambaran variabel mana yang paling berpengaruh terhadap nilai overall. Kombinasi kedua metode ini memberikan dasar yang lebih kuat untuk memilih fitur yang relevan sebelum analisis multivariat atau pemodelan lanjutan dilakukan.


5 Feature Extraction / Principal Component Analysis (PCA)

Principal Component Analysis (PCA) merupakan teknik reduksi dimensi yang mentransformasi variabel-variabel asli yang saling berkorelasi menjadi sekumpulan komponen utama yang ortogonal (tidak berkorelasi satu sama lain). Tujuannya adalah meringkas sebanyak mungkin informasi (varians) dari data asli ke dalam sejumlah kecil komponen, sehingga analisis menjadi lebih efisien dan mudah diinterpretasikan.

Pada tahap ini, PCA diterapkan terhadap seluruh variabel hasil feature engineering — mencakup 35 atribut skill asli ditambah 3 variabel baru (Is_Wonderkid, Goal_Contribution_Potential, Physical_Dominance) — menggunakan standardisasi skala (scale = TRUE) karena variabel-variabel tersebut memiliki satuan dan skala yang berbeda.

5.1 Persiapan Data PCA

library(tidyverse)
library(factoextra)
library(knitr)

# Variabel yang akan digunakan dalam PCA:
# variabel_skill (35 atribut) + 3 variabel hasil feature engineering
pca_vars <- c(variabel_skill, fitur_baru)

# Subset data numerik untuk PCA (tanpa NA)
df_pca_input <- df_fe %>%
  select(short_name, player_positions, overall, age, potential,
         all_of(pca_vars)) %>%
  drop_na(all_of(pca_vars))

cat("Jumlah observasi untuk PCA:", nrow(df_pca_input), "\n")
## Jumlah observasi untuk PCA: 16343
cat("Jumlah variabel input PCA :", length(pca_vars), "\n")
## Jumlah variabel input PCA : 38

Standardisasi skala wajib diterapkan karena variabel baru hasil feature engineering (Goal_Contribution_Potential, Physical_Dominance) memiliki rentang nilai yang berbeda dari variabel atribut asli (0–100). Tanpa standardisasi, variabel dengan varians besar akan mendominasi komponen utama secara artifisial.

5.2 Eksekusi PCA

# Menjalankan PCA dengan standardisasi skala
pca_result <- prcomp(
  df_pca_input %>% select(all_of(pca_vars)),
  scale = TRUE
)

# Membalik arah kutub PC1 agar Nilai Positif = Atribut Ofensif Tinggi
pca_result$rotation[, "PC1"] <- -pca_result$rotation[, "PC1"]
pca_result$x[, "PC1"]        <- -pca_result$x[, "PC1"]

# Ringkasan PCA
summary_pca <- summary(pca_result)

5.3 Analisis Proportion of Variance

5.3.1 Tabel Proportion of Variance

# Mengambil informasi varians dari ringkasan PCA
var_info <- summary_pca$importance

# Membuat tabel untuk 10 PC pertama
tabel_variance <- data.frame(
  # Komponen        = paste0("PC", 1:10),
  Standar_Deviasi = round(pca_result$sdev[1:10], 4),
  Prop_Variance   = round(var_info["Proportion of Variance", 1:10], 4),
  Kum_Variance    = round(var_info["Cumulative Proportion", 1:10], 4)
)

kable(
  tabel_variance,
  col.names = c("Standar Deviasi", "Proporsi Varians",
                "Varians Kumulatif"),
  caption   = "Tabel Proportion of Variance Hasil PCA (10 PC Pertama)",
  align     = "lrrr"
)
Tabel Proportion of Variance Hasil PCA (10 PC Pertama)
Standar Deviasi Proporsi Varians Varians Kumulatif
PC1 3.9781 0.4165 0.4165
PC2 2.9098 0.2228 0.6393
PC3 1.9166 0.0967 0.7359
PC4 1.7172 0.0776 0.8135
PC5 1.0379 0.0284 0.8419
PC6 0.8720 0.0200 0.8619
PC7 0.7912 0.0165 0.8784
PC8 0.7372 0.0143 0.8927
PC9 0.6715 0.0119 0.9045
PC10 0.6424 0.0109 0.9154

5.3.2 Interpretasi Proportion of Variance

prop_var  <- var_info["Proportion of Variance", ]
cum_var   <- var_info["Cumulative Proportion",  ]

# Berapa PC untuk mencapai 80% dan 85%
pc_80 <- which(cum_var >= 0.80)[1]
pc_85 <- which(cum_var >= 0.85)[1]

cat(sprintf("PC1 menjelaskan %.2f%% varians total.\n",  prop_var[1]*100))
## PC1 menjelaskan 41.65% varians total.
cat(sprintf("PC2 menjelaskan %.2f%% varians total.\n",  prop_var[2]*100))
## PC2 menjelaskan 22.28% varians total.
cat(sprintf("PC1 + PC2 kumulatif         : %.2f%%\n",   cum_var[2]*100))
## PC1 + PC2 kumulatif         : 63.93%
cat(sprintf("PC1 – PC3 kumulatif         : %.2f%%\n",   cum_var[3]*100))
## PC1 – PC3 kumulatif         : 73.59%
cat(sprintf("PC1 – PC4 kumulatif         : %.2f%%\n",   cum_var[4]*100))
## PC1 – PC4 kumulatif         : 81.35%
cat(sprintf("\nUntuk mencapai >= 80%% varians diperlukan %d PC.\n", pc_80))
## 
## Untuk mencapai >= 80% varians diperlukan 4 PC.
cat(sprintf("Untuk mencapai >= 85%% varians diperlukan %d PC.\n", pc_85))
## Untuk mencapai >= 85% varians diperlukan 6 PC.

Interpretasi: Hasil PCA menunjukkan bahwa PC1 saja mampu menjelaskan sekitar 41,65% varians total, mengindikasikan adanya satu dimensi dominan yang mencerminkan atribut teknik pemain lapangan secara umum. PC2 menambahkan sekitar 22,28% varians, sehingga dua komponen pertama secara kumulatif menjelaskan ±63,93% varians. Empat komponen pertama (PC1–PC4) berhasil merangkum ±81,35% varians dari 38 variabel asal.

Dengan demikian, reduksi dimensi kelompok ini berhasil: dari 38 variabel, hanya 4 komponen utama yang diperlukan untuk merepresentasikan lebih dari 80% informasi data. Ini membuktikan bahwa terdapat struktur korelasi yang kuat antar atribut pemain, sehingga informasinya dapat dipadatkan secara efektif.

Sebagai acuan tambahan, eigenvalue dari PC1 hingga PC4 semuanya melebihi nilai 1 (kriteria Kaiser Rule), yang mengonfirmasi bahwa keempat komponen tersebut layak dipertahankan sebagai komponen bermakna.

# Eigenvalues = sdev^2
eigenvalues <- pca_result$sdev^2
tabel_eigen <- data.frame(
  Komponen   = paste0("PC", 1:10),
  Eigenvalue = round(eigenvalues[1:10], 4),
  Status     = ifelse(eigenvalues[1:10] > 1, "Pertahankan (> 1)", "Abaikan (<= 1)")
)

kable(
  tabel_eigen,
  caption = "Eigenvalue Komponen Utama dan Keputusan Kaiser Rule",
  align   = "lrr"
)
Eigenvalue Komponen Utama dan Keputusan Kaiser Rule
Komponen Eigenvalue Status
PC1 15.8257 Pertahankan (> 1)
PC2 8.4667 Pertahankan (> 1)
PC3 3.6732 Pertahankan (> 1)
PC4 2.9487 Pertahankan (> 1)
PC5 1.0771 Pertahankan (> 1)
PC6 0.7603 Abaikan (<= 1)
PC7 0.6260 Abaikan (<= 1)
PC8 0.5434 Abaikan (<= 1)
PC9 0.4509 Abaikan (<= 1)
PC10 0.4127 Abaikan (<= 1)

5.4 Scree Plot

fviz_eig(
  pca_result,
  addlabels  = TRUE,
  ylim       = c(0, 45),
  barfill    = "steelblue",
  barcolor   = "white",
  linecolor  = "tomato",
  ncp        = 15,
  main       = "Scree Plot – Proporsi Varians Tiap Komponen Utama",
  xlab       = "Komponen Utama",
  ylab       = "Persentase Varians yang Dijelaskan (%)"
) +
  geom_hline(
    yintercept = 100 / length(pca_vars),
    linetype   = "dashed",
    color      = "darkgreen",
    linewidth  = 0.8
  ) +
  annotate(
    "text", x = 12, y = 100 / length(pca_vars) + 0.8,
    label = "Rata-rata varians per variabel",
    color = "darkgreen", size = 3
  )
Scree Plot Hasil PCA

Scree Plot Hasil PCA

Membaca Scree Plot: Scree plot menampilkan besarnya varians yang dijelaskan oleh masing-masing PC secara berurutan. “Siku” (elbow) grafik terdapat pada PC5, di mana terjadi penurunan drastis dari PC4 ke PC5 (dari ~7,76% menjadi ~2,83%). Ini menguatkan keputusan mempertahankan 4 komponen utama berdasarkan Kaiser Rule. Garis putus-putus hijau menunjukkan rata-rata varians per variabel (100%/38 ≈ 2,63%); komponen yang berada di atas garis ini dianggap membawa informasi di atas rata-rata.

5.5 Analisis Loading Factor

Loading factor menunjukkan seberapa kuat kontribusi setiap variabel asli terhadap masing-masing komponen utama. Nilai positif mengindikasikan variabel berkontribusi searah dengan komponen, sedangkan nilai negatif menunjukkan arah berlawanan.

# Mengambil loading factor (matriks rotasi)
loadings_df <- as.data.frame(pca_result$rotation[, 1:4])
loadings_df$Variabel <- rownames(loadings_df)

# Sempurnakan fungsi select dengan menyertakan kolom Variabel
loadings_df <- loadings_df %>%
  select(Variabel, PC1, PC2, PC3, PC4) %>% 
  arrange(desc(abs(PC1)))

kable(
  loadings_df %>% mutate(across(PC1:PC4, ~round(., 4))),
  caption = "Loading Factor Variabel pada PC1 hingga PC4",
  align   = "lrrrr"
)
Loading Factor Variabel pada PC1 hingga PC4
Variabel PC1 PC2 PC3 PC4
dribbling dribbling 0.2366 0.0142 0.0812 -0.0132
Goal_Contribution_Potential Goal_Contribution_Potential 0.2295 -0.0761 -0.1454 -0.0546
skill_dribbling skill_dribbling 0.2265 -0.0141 0.0681 -0.0275
shooting shooting 0.2263 -0.0824 -0.1432 -0.0532
power_long_shots power_long_shots 0.2217 -0.0502 -0.0973 -0.0911
mentality_positioning mentality_positioning 0.2210 -0.0648 -0.0493 -0.0197
mentality_vision mentality_vision 0.2204 0.0257 0.0406 -0.1380
passing passing 0.2204 0.1068 0.0907 -0.1384
skill_ball_control skill_ball_control 0.2201 0.0717 0.0060 -0.0498
skill_curve skill_curve 0.2147 0.0086 0.0634 -0.0975
attacking_finishing attacking_finishing 0.2118 -0.1150 -0.1390 -0.0346
power_shot_power power_shot_power 0.2082 -0.0050 -0.1660 -0.0510
attacking_volleys attacking_volleys 0.2045 -0.0820 -0.1593 -0.0454
skill_fk_accuracy skill_fk_accuracy 0.1971 -0.0050 0.0023 -0.1646
attacking_crossing attacking_crossing 0.1892 0.0443 0.1812 -0.0609
mentality_composure mentality_composure 0.1860 0.1433 -0.0731 -0.0369
attacking_short_passing attacking_short_passing 0.1811 0.1719 0.0307 -0.1161
mentality_penalties mentality_penalties 0.1811 -0.0842 -0.1992 -0.0569
movement_agility movement_agility 0.1742 -0.0792 0.2402 0.1259
Physical_Dominance Physical_Dominance 0.1623 0.1041 0.0440 0.3887
movement_reactions movement_reactions 0.1592 0.1906 -0.0725 0.0206
skill_long_passing skill_long_passing 0.1505 0.1892 0.0959 -0.1790
movement_balance movement_balance 0.1343 -0.0816 0.2922 0.0197
movement_acceleration movement_acceleration 0.1342 -0.0984 0.2453 0.3308
pace pace 0.1284 -0.0916 0.2225 0.3805
movement_sprint_speed movement_sprint_speed 0.1145 -0.0794 0.1881 0.3939
power_stamina power_stamina 0.1057 0.1773 0.0368 0.1870
power_jumping power_jumping 0.0585 0.1868 -0.2609 0.3300
defending_sliding_tackle defending_sliding_tackle -0.0461 0.2983 0.1837 -0.0722
defending_standing_tackle defending_standing_tackle -0.0372 0.3041 0.1734 -0.0756
defending defending -0.0342 0.3188 0.1410 -0.0608
defending_marking_awareness defending_marking_awareness -0.0341 0.3092 0.1498 -0.0622
physic physic 0.0316 0.2648 -0.2264 0.2101
mentality_interceptions mentality_interceptions -0.0288 0.3069 0.1602 -0.0727
mentality_aggression mentality_aggression 0.0278 0.2747 -0.0598 0.0408
Is_Wonderkid Is_Wonderkid 0.0218 -0.0053 0.0389 0.0073
power_strength power_strength -0.0153 0.2042 -0.3250 0.1985
attacking_heading_accuracy attacking_heading_accuracy 0.0143 0.1927 -0.3203 0.1324

5.5.1 Visualisasi Top Loading Per Komponen

# PC1 – Top 12 variabel
p1 <- loadings_df %>%
  slice_head(n = 12) %>%
  ggplot(aes(x = reorder(Variabel, abs(PC1)), y = PC1,
             fill = PC1 > 0)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  scale_fill_manual(values = c("tomato", "steelblue")) +
  labs(title = "PC1 – Top 12 Loading Factor",
       x = NULL, y = "Loading") +
  theme_bw(base_size = 11)

# PC2 – Top 12 variabel
p2 <- as.data.frame(pca_result$rotation[, 1:4])
p2$Variabel <- rownames(p2)
p2 <- p2 %>% arrange(desc(abs(PC2))) %>% slice_head(n = 12) %>%
  ggplot(aes(x = reorder(Variabel, abs(PC2)), y = PC2,
             fill = PC2 > 0)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  scale_fill_manual(values = c("tomato", "steelblue")) +
  labs(title = "PC2 – Top 12 Loading Factor",
       x = NULL, y = "Loading") +
  theme_bw(base_size = 11)

gridExtra::grid.arrange(p1, p2, ncol = 2)

# PC3
p3 <- as.data.frame(pca_result$rotation[, 1:4])
p3$Variabel <- rownames(p3)
p3 <- p3 %>% arrange(desc(abs(PC3))) %>% slice_head(n = 12) %>%
  ggplot(aes(x = reorder(Variabel, abs(PC3)), y = PC3,
             fill = PC3 > 0)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  scale_fill_manual(values = c("tomato", "steelblue")) +
  labs(title = "PC3 – Top 12 Loading Factor",
       x = NULL, y = "Loading") +
  theme_bw(base_size = 11)

# PC4
p4 <- as.data.frame(pca_result$rotation[, 1:4])
p4$Variabel <- rownames(p4)
p4 <- p4 %>% arrange(desc(abs(PC4))) %>% slice_head(n = 12) %>%
  ggplot(aes(x = reorder(Variabel, abs(PC4)), y = PC4,
             fill = PC4 > 0)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  scale_fill_manual(values = c("tomato", "steelblue")) +
  labs(title = "PC4 – Top 12 Loading Factor",
       x = NULL, y = "Loading") +
  theme_bw(base_size = 11)

gridExtra::grid.arrange(p3, p4, ncol = 2)

5.5.2 Penamaan Komponen Utama

Berdasarkan analisis loading factor, setiap komponen utama dapat diberi nama substantif sebagai berikut:

PC1 — “Kemampuan Teknik Menyerang & Kreativitas” PC1 memiliki loading positif tinggi pada variabel dribbling, skill_dribbling, shooting, Goal_Contribution_Potential, power_long_shots, mentality_positioning, mentality_vision, passing, dan skill_ball_control. Komponen ini merangkum kemampuan teknis ofensif pemain lapangan secara menyeluruh: kualitas mengolah bola, ketajaman penyelesaian, dan kecerdasan membaca permainan. Pemain dengan skor PC1 tinggi adalah pemain berkualifikasi tinggi secara teknis — tipikal midfielder kreatif atau penyerang skillful.

PC2 — “Orientasi Bertahan & Kekuatan Fisik Defensif” PC2 didominasi loading positif pada defending, defending_marking_awareness, mentality_interceptions, defending_standing_tackle, defending_sliding_tackle, dan mentality_aggression. Komponen ini mencerminkan profil pemain dengan spesialisasi bertahan — center-back, defensive midfielder, atau pemain dengan gaya main keras dan agresif. Nilai PC2 tinggi mengindikasikan pemain yang lebih mengutamakan pertahanan daripada kreasi serangan.

PC3 — “Kekuatan Fisik Statis vs. Kelincahan Dinamis” PC3 memiliki loading positif pada power_strength, attacking_heading_accuracy, dan power_jumping, namun loading negatif pada movement_balance, movement_agility, dan movement_acceleration. Komponen ini membedakan pemain berbadan besar dan kuat (menang duel udara, fisik dominan) dengan pemain yang gesit dan lincah. Skor PC3 tinggi = pemain tipe target man atau bek tinggi; skor rendah = pemain cepat dan lincah.

PC4 — “Kecepatan & Daya Ledak Fisik” PC4 didominasi loading positif pada movement_sprint_speed, Physical_Dominance, pace, dan movement_acceleration. Komponen ini secara spesifik mengukur dimensi kecepatan berlari dan daya ledak sprint — sesuatu yang tidak sepenuhnya tertangkap oleh PC1–PC3. Variabel Physical_Dominance yang merupakan hasil feature engineering memiliki loading tinggi di sini, menunjukkan relevansinya dalam menangkap dimensi fisik yang unik.

tabel_pc <- data.frame(
  Komponen = c("PC1", "PC2", "PC3", "PC4"),
  Nama_Substantif = c(
    "Kemampuan Teknik Menyerang & Kreativitas",
    "Orientasi Bertahan & Kekuatan Fisik Defensif",
    "Kekuatan Fisik Statis vs. Kelincahan Dinamis",
    "Kecepatan & Daya Ledak Fisik"
  ),
  Varians_Dijelaskan = c("41.65%", "22.28%", "9.67%", "7.76%"),
  Variabel_Kunci = c(
    "dribbling, shooting, Goal_Contribution_Potential, passing, mentality_vision",
    "defending, defending_marking_awareness, mentality_interceptions, defending_standing_tackle",
    "power_strength, attacking_heading_accuracy (+) vs. movement_balance, movement_agility (-)",
    "movement_sprint_speed, Physical_Dominance, pace, movement_acceleration"
  )
)

kable(
  tabel_pc,
  col.names = c("Komponen", "Nama Substantif", "Varians Dijelaskan", "Variabel Kunci"),
  caption   = "Ringkasan Penamaan dan Interpretasi Komponen Utama PCA",
  align     = "llrr"
)
Ringkasan Penamaan dan Interpretasi Komponen Utama PCA
Komponen Nama Substantif Varians Dijelaskan Variabel Kunci
PC1 Kemampuan Teknik Menyerang & Kreativitas 41.65% dribbling, shooting, Goal_Contribution_Potential, passing, mentality_vision
PC2 Orientasi Bertahan & Kekuatan Fisik Defensif 22.28% defending, defending_marking_awareness, mentality_interceptions, defending_standing_tackle
PC3 Kekuatan Fisik Statis vs. Kelincahan Dinamis 9.67% power_strength, attacking_heading_accuracy (+) vs. movement_balance, movement_agility (-)
PC4 Kecepatan & Daya Ledak Fisik 7.76% movement_sprint_speed, Physical_Dominance, pace, movement_acceleration

5.6 Biplot PCA

Biplot menampilkan secara bersamaan posisi observasi (pemain) dalam ruang komponen utama dan arah panah variabel (loading vector). Panjang panah menunjukkan kekuatan kontribusi variabel, sementara sudut antar panah mengindikasikan korelasi.

# Menyiapkan skor PCA dengan informasi pemain
pca_scores_df <- as.data.frame(pca_result$x[, 1:4])
pca_scores_df$short_name       <- df_pca_input$short_name
pca_scores_df$player_positions <- df_pca_input$player_positions
pca_scores_df$overall          <- df_pca_input$overall
pca_scores_df$age              <- df_pca_input$age
pca_scores_df$Is_Wonderkid     <- df_pca_input$Is_Wonderkid

# Biplot standar menggunakan factoextra
fviz_pca_biplot(
  pca_result,
  axes           = c(1, 2),
  geom.ind       = "point",
  col.ind        = "cos2",
  gradient.cols  = c("#00AFBB", "#E7B800", "#FC4E07"),
  col.var        = "black",
  repel          = TRUE,
  label          = "var",
  alpha.ind      = 0.3,
  title          = "Biplot PCA – PC1 (Teknik Menyerang) vs PC2 (Kemampuan Bertahan)",
  legend.title   = "Kualitas Representasi (cos²)"
)
Biplot PC1 vs PC2

Biplot PC1 vs PC2

Membaca Biplot:

  1. Panah variabel: Panah yang mengarah ke kanan (positif PC1) mewakili variabel teknik menyerang (dribbling, shooting, passing). Panah yang mengarah ke atas (positif PC2) mewakili variabel bertahan (defending, mentality_interceptions). Variabel goalkeeping secara konsisten terletak terpisah karena telah dihapus dari dataset, sementara atribut kiper yang tersisa memiliki loading lemah.

  2. Posisi pemain: Pemain yang terletak di kuadran kanan-bawah merupakan pemain dengan kemampuan teknik menyerang tinggi namun bertahan rendah (tipikal penyerang). Pemain di kuadran kanan-atas memiliki profil dua sisi (box-to-box midfielder). Pemain di kuadran kiri-atas adalah spesialis bertahan.

  3. Sudut antar panah: Variabel-variabel dalam kelompok yang sama (misal: defending, defending_marking_awareness, mentality_interceptions) membentuk sudut kecil antara satu sama lain, menandakan korelasi tinggi — konsisten dengan temuan filter method sebelumnya.

# Biplot yang menyoroti posisi wonderkid
pca_scores_df %>%
  mutate(Kategori = ifelse(Is_Wonderkid == 1, "Wonderkid", "Non-Wonderkid")) %>%
  ggplot(aes(x = PC1, y = PC2, color = Kategori, alpha = Kategori)) +
  geom_point(size = 1.2) +
  scale_color_manual(values = c("Non-Wonderkid" = "gray70",
                                "Wonderkid"     = "#E63946")) +
  scale_alpha_manual(values = c("Non-Wonderkid" = 0.25,
                                "Wonderkid"     = 0.85)) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray40") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray40") +
  labs(
    title    = "Distribusi Wonderkid dalam Ruang PC1 vs PC2",
    subtitle = "Wonderkid = Usia ≤ 21 tahun & Potential ≥ 80",
    x        = "PC1 – Kemampuan Teknik Menyerang & Kreativitas",
    y        = "PC2 – Orientasi Bertahan & Kekuatan Fisik Defensif",
    color    = "Kategori",
    alpha    = "Kategori"
  ) +
  theme_bw(base_size = 12)
Distribusi Wonderkid dalam Ruang PCA

Distribusi Wonderkid dalam Ruang PCA

5.7 Identifikasi Wonderkid Berdasarkan Skor PCA

# Menampilkan 15 wonderkid dengan skor PC1 tertinggi
top_wonderkid <- pca_scores_df %>%
  filter(Is_Wonderkid == 1) %>%
  arrange(desc(PC1)) %>%
  slice_head(n = 15) %>%
  select(short_name, player_positions, overall, age, PC1, PC2) %>%
  mutate(across(c(PC1, PC2), ~round(., 3)))

kable(
  top_wonderkid,
  col.names = c("Nama Pemain", "Posisi", "Overall", "Usia",
                "PC1 (Teknik Menyerang)", "PC2 (Bertahan)"),
  caption   = "15 Wonderkid dengan Skor PC1 (Kemampuan Teknik Menyerang) Tertinggi",
  align     = "llrrrr"
)
15 Wonderkid dengan Skor PC1 (Kemampuan Teknik Menyerang) Tertinggi
Nama Pemain Posisi Overall Usia PC1 (Teknik Menyerang) PC2 (Bertahan)
Lamine Yamal RM, RW 89 17 10.989 -3.089
D. Doué RW, LW, CM, RM 85 20 10.079 1.614
R. Cherki RW, RM, CAM 81 21 9.068 -2.524
K. Yıldız CAM, LM, LW, CM 79 20 8.631 -1.462
A. Güler RM, CAM, RW 81 20 8.408 -0.860
João Neves CM, CDM 85 20 8.338 6.195
Savinho RW, LW, RM 82 21 8.334 -2.578
Estêvão RM, CAM, RW 78 18 8.326 -2.572
A. Garnacho CAM, LW, LM, CM 77 21 7.819 -2.228
M. Tel ST, LW, CAM 77 20 7.582 -2.776
A. Fatawu RM, RW 76 21 7.374 -0.401
J. Gittens LM, LW 78 20 7.106 -3.414
F. Mastantuono CAM, RW, ST 77 17 7.074 0.100
Endrick ST, RW 77 18 6.996 -2.143
Gavi CM, CAM 83 20 6.987 3.453

Interpretasi: Wonderkid yang berada di puncak skor PC1 adalah pemain muda dengan kemampuan teknik menyerang yang sudah menonjol di usianya. Sebagian besar di antaranya memiliki skor PC2 negatif atau rendah, yang mengonfirmasi bahwa mereka adalah pemain yang berorientasi menyerang, bukan bertahan.


6 Insight dan Kesimpulan

6.1 Ringkasan Temuan Analitik

6.1.1 Temuan 1: Struktur Atribut Pemain Lapangan Bersifat Multidimensi Namun Terstruktur

Hasil PCA membuktikan bahwa meskipun dataset FC 26 memiliki 38 variabel, struktur informasinya dapat dirangkum ke dalam empat dimensi utama yang memiliki makna substantif jelas. Keempat dimensi ini tidak bersifat arbitrer, melainkan mencerminkan realitas sepak bola:

  • Dimensi Teknik Menyerang (PC1): Komponen terbesar, mencakup semua aspek kreativitas dan penyelesaian.
  • Dimensi Kemampuan Bertahan (PC2): Komponen kedua, memisahkan pemain bertahan dari pemain kreatif.
  • Dimensi Fisik Statis–Dinamis (PC3): Membedakan pemain bertubuh besar (heading, strength) dengan pemain gesit.
  • Dimensi Kecepatan Eksplosif (PC4): Mengukur daya ledak lari secara spesifik.

Keberhasilan merangkum >80% varians dari 38 variabel ke dalam 4 komponen membuktikan bahwa atribut pemain sepak bola tidak independen satu sama lain — ada pola korelasi yang kuat dan bermakna.

6.1.2 Temuan 2: Variabel Hasil Feature Engineering Berperan Signifikan

Variabel baru yang dibuat pada tahap feature engineering terbukti berkontribusi secara substantif dalam PCA:

  • Goal_Contribution_Potential memiliki loading tinggi di PC1, mengonfirmasi bahwa kemampuan berkontribusi gol merupakan bagian inti dari dimensi teknik menyerang.
  • Physical_Dominance memiliki loading dominan di PC4, menunjukkan bahwa variabel komposit ini berhasil menangkap dimensi kecepatan dan daya ledak fisik yang tidak sepenuhnya terwakili oleh variabel tunggal mana pun.
  • Is_Wonderkid memiliki loading yang lebih moderat, namun secara konsisten berasosiasi dengan PC1 yang tinggi pada visualisasi distribusi wonderkid.

Ini memvalidasi bahwa proses feature engineering yang dilakukan kelompok berhasil membentuk variabel yang substantif dan informatif secara statistik.

6.1.3 Temuan 3: Pola Gaya Main Pemain Teridentifikasi Secara Sistematis

Melalui posisi pemain dalam ruang PC1–PC2, empat kuadran gaya main dapat diidentifikasi:

# Visualisasi kuadran gaya main
pca_scores_df %>%
  mutate(
    # Klasifikasi posisi utama berdasarkan player_positions
    Posisi_Utama = case_when(
      grepl("ST|CF|LW|RW|LF|RF", player_positions) ~ "Penyerang",
      grepl("CAM|LAM|RAM|LM|RM|CM|LCM|RCM", player_positions) ~ "Gelandang",
      grepl("CDM|LDM|RDM|LWB|RWB|LB|RB|CB|LCB|RCB", player_positions) ~ "Bek",
      TRUE ~ "Lainnya"
    )
  ) %>%
  filter(Posisi_Utama != "Lainnya") %>%
  ggplot(aes(x = PC1, y = PC2, color = Posisi_Utama)) +
  geom_point(alpha = 0.35, size = 1.0) +
  stat_ellipse(level = 0.75, linewidth = 1.0) +
  scale_color_manual(values = c(
    "Penyerang" = "#E63946",
    "Gelandang" = "#2A9D8F",
    "Bek"       = "#264653"
  )) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray50") +
  annotate("text", x =  9, y = -7, label = "Penyerang\nSkillful", size = 3.5,
           fontface = "bold", color = "#E63946") +
  annotate("text", x =  6, y =  6, label = "Gelandang\nBox-to-Box", size = 3.5,
           fontface = "bold", color = "#2A9D8F") +
  annotate("text", x = -7, y =  6, label = "Bek /\nGelandang Bertahan", size = 3.5,
           fontface = "bold", color = "#264653") +
  annotate("text", x = -5, y = -6, label = "Pemain\nNilaiannya Rendah", size = 3.5,
           fontface = "italic", color = "gray50") +
  labs(
    title    = "Pola Gaya Main Berdasarkan Ruang PC1 vs PC2",
    subtitle = "Elips pada tingkat kepercayaan 75% per kelompok posisi",
    x        = "PC1 – Kemampuan Teknik Menyerang",
    y        = "PC2 – Orientasi Bertahan",
    color    = "Posisi Utama"
  ) +
  theme_bw(base_size = 12)

Analisis Pola Gaya Main:

  • Penyerang terkonsentrasi di kuadran kanan-bawah (PC1 tinggi, PC2 rendah): kemampuan teknik menyerang tinggi namun kemampuan bertahan rendah — sesuai peran posisional mereka.
  • Bek terkonsentrasi di kuadran kiri-atas (PC1 rendah, PC2 tinggi): atribut teknik menyerang terbatas namun kemampuan bertahan kuat.
  • Gelandang memiliki sebaran yang lebih luas dan cenderung berada di area tengah hingga kanan-atas, mencerminkan variasi peran gelandang: dari deep-lying playmaker (PC2 lebih tinggi) hingga attacking midfielder (PC1 lebih tinggi).

6.1.4 Temuan 4: Wonderkid Memiliki Profil Teknik Menyerang di Atas Rata-rata

# Statistik rata-rata skor PCA untuk wonderkid vs non-wonderkid
perbandingan_wk <- pca_scores_df %>%
  mutate(Kategori = ifelse(Is_Wonderkid == 1, "Wonderkid", "Non-Wonderkid")) %>%
  group_by(Kategori) %>%
  summarise(
    N          = n(),
    Rata_PC1   = round(mean(PC1), 3),
    Rata_PC2   = round(mean(PC2), 3),
    Rata_PC3   = round(mean(PC3), 3),
    Rata_PC4   = round(mean(PC4), 3),
    .groups    = "drop"
  )

kable(
  perbandingan_wk,
  col.names = c("Kategori", "Jumlah", 
                "Rata-rata PC1 (Teknik Menyerang)",
                "Rata-rata PC2 (Bertahan)", 
                "Rata-rata PC3 (Fisik Statis–Dinamis)",
                "Rata-rata PC4 (Kecepatan)"),
  caption   = "Perbandingan Rata-rata Skor PCA: Wonderkid vs Non-Wonderkid",
  align     = "lrrrrr", # 6 karakter untuk 6 kolom Anda
  digits    = 3
)
Perbandingan Rata-rata Skor PCA: Wonderkid vs Non-Wonderkid
Kategori Jumlah Rata-rata PC1 (Teknik Menyerang) Rata-rata PC2 (Bertahan) Rata-rata PC3 (Fisik Statis–Dinamis) Rata-rata PC4 (Kecepatan)
Non-Wonderkid 15668 -0.072 0.009 -0.030 -0.004
Wonderkid 675 1.661 -0.217 0.689 0.104

Wonderkid memiliki rata-rata skor PC1 yang lebih tinggi dibandingkan pemain non-wonderkid, mengindikasikan bahwa pemain muda dengan potensi tinggi pada umumnya sudah unggul dalam dimensi teknik menyerang bahkan pada usia dini. Perbedaan ini bermakna praktis dalam konteks scouting: PC1 dapat dijadikan indikator awal kualitas teknik pemain muda.

6.2 Kesimpulan Akhir

Analisis yang telah dilakukan kelompok ini mencakup rangkaian tahapan yang komprehensif terhadap dataset FC 26, mulai dari eksplorasi awal, pembersihan data, rekayasa fitur, seleksi fitur, hingga reduksi dimensi melalui PCA. Berikut adalah kesimpulan akhir yang dapat ditarik:

tabel_kesimpulan <- data.frame(
  No = 1:5,
  Aspek = c(
    "Kualitas Dataset",
    "Feature Engineering",
    "Feature Selection",
    "Reduksi Dimensi (PCA)",
    "Pola Wonderkid"
  ),
  Kesimpulan = c(
    "Dataset FC 26 (18.405 pemain, 110 variabel) berkualitas baik setelah penghapusan GK dan missing value. Data final untuk PCA mencakup 16.343 pemain lapangan dengan 38 variabel.",
    "Tiga variabel baru berhasil dibentuk (Is_Wonderkid, Goal_Contribution_Potential, Physical_Dominance) dan terbukti signifikan secara statistik dalam PCA, khususnya Goal_Contribution_Potential (loading tinggi di PC1) dan Physical_Dominance (loading tinggi di PC4).",
    "Filter method mengidentifikasi variabel-variabel redundan (korelasi |r| > 0,80). Random Forest mengonfirmasi variabel dengan kontribusi prediktif terbesar terhadap overall rating. Kombinasi keduanya menghasilkan seleksi fitur yang lebih andal.",
    "PCA berhasil meringkas 38 variabel menjadi 4 komponen utama yang menjelaskan >81% varians total. Keempat komponen memiliki makna substantif: Teknik Menyerang (PC1), Kemampuan Bertahan (PC2), Fisik Statis vs. Dinamis (PC3), dan Kecepatan Eksplosif (PC4). Reduksi dimensi ini dinyatakan BERHASIL.",
    "Terdapat 675 wonderkid (pemain usia ≤21, potential ≥80). Wonderkid cenderung memiliki skor PC1 di atas rata-rata, mengonfirmasi bahwa kemampuan teknik menyerang merupakan karakteristik utama pemain muda berbakat dalam dataset ini."
  )
)

kable(
  tabel_kesimpulan,
  col.names = c("No.", "Aspek", "Kesimpulan"),
  caption   = "Kesimpulan Akhir Analisis Multivariat Dataset FC 26",
  align     = "cll"
)
Kesimpulan Akhir Analisis Multivariat Dataset FC 26
No. Aspek Kesimpulan
1 Kualitas Dataset Dataset FC 26 (18.405 pemain, 110 variabel) berkualitas baik setelah penghapusan GK dan missing value. Data final untuk PCA mencakup 16.343 pemain lapangan dengan 38 variabel.
2 Feature Engineering Tiga variabel baru berhasil dibentuk (Is_Wonderkid, Goal_Contribution_Potential, Physical_Dominance) dan terbukti signifikan secara statistik dalam PCA, khususnya Goal_Contribution_Potential (loading tinggi di PC1) dan Physical_Dominance (loading tinggi di PC4).
3 Feature Selection Filter method mengidentifikasi variabel-variabel redundan (korelasi |r| > 0,80). Random Forest mengonfirmasi variabel dengan kontribusi prediktif terbesar terhadap overall rating. Kombinasi keduanya menghasilkan seleksi fitur yang lebih andal.
4 Reduksi Dimensi (PCA) PCA berhasil meringkas 38 variabel menjadi 4 komponen utama yang menjelaskan >81% varians total. Keempat komponen memiliki makna substantif: Teknik Menyerang (PC1), Kemampuan Bertahan (PC2), Fisik Statis vs. Dinamis (PC3), dan Kecepatan Eksplosif (PC4). Reduksi dimensi ini dinyatakan BERHASIL.
5 Pola Wonderkid Terdapat 675 wonderkid (pemain usia ≤21, potential ≥80). Wonderkid cenderung memiliki skor PC1 di atas rata-rata, mengonfirmasi bahwa kemampuan teknik menyerang merupakan karakteristik utama pemain muda berbakat dalam dataset ini.

6.2.1 Implikasi Praktis

Hasil analisis ini memiliki sejumlah implikasi praktis bagi pengguna data sepak bola:

  1. Efisiensi Scouting: Daripada mengevaluasi 38 atribut secara manual, empat skor komponen utama (PC1–PC4) dapat digunakan sebagai profil ringkas seorang pemain. Pemain dengan PC1 dan PC4 tinggi adalah calon pemain muda yang eksplosif dan skillful.

  2. Pengelompokan Taktis: Visualisasi biplot PC1 vs PC2 menunjukkan bahwa pemain secara alami mengelompok berdasarkan peran taktisnya, yang dapat mendukung analisis keseimbangan skuad.

  3. Validasi Feature Engineering: Variabel komposit Goal_Contribution_Potential dan Physical_Dominance terbukti secara statistik mampu merangkum dimensi bermakna yang tidak tertangkap sepenuhnya oleh satu variabel tunggal.

  4. Dasar Analisis Lanjutan: Skor PC1–PC4 yang telah dihasilkan dapat digunakan sebagai input pada analisis klaster (cluster analysis) atau model regresi untuk memprediksi nilai transfer pemain, sebagai langkah analisis multivariat selanjutnya.

6.2.2 Keterbatasan

Analisis ini memiliki beberapa keterbatasan yang perlu diperhatikan:

  • Data bersumber dari video game FC 26, bukan data performa nyata di lapangan, sehingga atribut yang ada adalah penilaian subjektif pengembang game.
  • PCA bersifat linear dan tidak dapat menangkap hubungan nonlinear antarvariabel.
  • Interpretasi loading factor bersifat tentatif dan tergantung pada rotasi yang digunakan.

Analisis ini diselesaikan menggunakan R dengan paket tidyverse, factoextra, randomForest, corrplot, dan knitr. Dataset: FC 26 Player Dataset (Kaggle, September 2025).