Praktikum Pemrograman Statistika

Wrangling Data Frame di R: Dasar-Dasar Pengelolaan Data

Author

Muhammad Yusran

Published

September 2, 2025

Sekilas Tentang Data Wrangling

Data wrangling—juga dikenal dengan istilah data munging atau data manipulation (dalam konotasi positif)—merupakan proses transformasi dan penyiapan data agar berada dalam format yang sesuai dan siap untuk dianalisis lebih lanjut. Proses ini sangat penting karena data mentah yang dikumpulkan dari berbagai sumber seringkali tidak langsung bisa digunakan dalam analisis statistik atau pemodelan.

Pada praktiknya, data wrangling menghadapi berbagai tantangan, seperti:

  • Ukuran data yang sangat besar (large-scale data)
  • Format data yang tidak seragam
  • Sumber data yang tersebar dan tidak terintegrasi
  • Nilai hilang atau tidak valid (missing/inconsistent values)

Sehingga tidak mengherankan jika tahapan wrangling ini dapat menyita hingga 80% waktu dan usaha dari keseluruhan proses analisis data.

Aktivitas utama dalam data wrangling antara lain:

  • Membuat kolom baru: Biasanya berasal dari hasil perhitungan atau transformasi kolom yang sudah ada.
  • Subsetting data: Memilih baris dan/atau kolom tertentu sesuai kriteria yang diinginkan.
  • Sorting data: Mengurutkan data berdasarkan satu atau lebih variabel.
  • Recoding: Mengubah atau menyederhanakan nilai-nilai dalam suatu kolom (misalnya kategorisasi umur).
  • Merging data: Menggabungkan dua atau lebih data frame, baik secara horizontal (kolom) maupun vertikal (baris).
  • Reshaping data: Mengubah struktur data dari format wide ke long atau sebaliknya untuk keperluan analisis tertentu.

Pada bagian ini akan dipraktikan bagaimana melakukan data wrangling menggunakan paket base atau paket-paket bawaan R lainnya.

Persiapan Data

Data yang digunakan dalam praktikum ini merupakan data pemain Real Madrid musim 2025/2026, yang discraping dari Transfermarkt. Untuk keperluan praktikum ini, data telah disederhanakan dan disusun ulang ke dalam beberapa data frame agar dapat digunakan sebagai contoh proses wrangling.

Berikut adalah struktur dan isi dari masing-masing data frame yang akan digunakan:

  • madrid.squad: berisi 11 pemain utama (starting lineup) yang dipilih berdasarkan posisi inti dalam formasi. Kolom: ID (nomor punggung), Name, Position, dan Age.
  • madrid.bench: berisi pemain cadangan (bench) yang tidak masuk ke starting lineup. Pemain muda dari akademi tidak dimasukkan ke dalam bench. Kolom: ID, Name, Position, dan Age.
  • madrid.academy: berisi daftar pemain yang berasal dari akademi atau tim muda Real Madrid. Digunakan sebagai latihan dalam segmentasi data berdasarkan kategori sumber pemain. Kolom: ID, Name, Position, dan Age.
  • madrid.nationality: menyajikan pasangan ID dan Nationality untuk seluruh pemain (squad, bench, dan academy). Cocok untuk latihan join/merge berdasarkan atribut non-numerik. Kolom: ID, Nationality.
  • madrid.market_value: menampilkan nilai pasar (MarketValue_BillionIDR) dalam satuan miliar Rupiah untuk seluruh pemain, kecuali yang berasal dari akademi. Kolom: ID, MarketValue_BillionIDR.
madrid.squad <- data.frame(
  ID = c(1, 12, 24, 22, 18, 14, 8, 5, 15, 7, 10),
  Name = c("Thibaut Courtois", "Trent Alexander-Arnold", "Dean Huijsen", "Antonio Rudiger",
           "Alvaro Carreras", "Aurelien Tchouameni", "Federico Valverde", "Jude Bellingham",
           "Arda Guler", "Vinicius Junior", "Kylian Mbappe"),
  Position = c("Goalkeeper", "Right Back", "Centre Back", "Centre Back",
               "Left Back", "Defensive Midfielder", "Central Midfielder", "Attacking Midfielder",
               "Attacking Midfielder", "Left Winger", "Striker"),
  Age = c(33, 26, 20, 32, 22, 25, 27, 22, 20, 25, 26)
)

madrid.squad
madrid.bench <- data.frame(
  ID = c(13, 3, 4, 20, 23, 2, 6, 19, 11, 21, 9),
  Name = c("Andriy Lunin", "Eder Militao", "David Alaba", "Fran Garcia", "Ferland Mendy",
           "Daniel Carvajal", "Eduardo Camavinga", "Dani Ceballos", "Rodrygo",
           "Brahim Diaz", "Endrick"),
  Position = c("Goalkeeper", "Centre Back", "Centre Back", "Left Back", "Left Back",
               "Right Back", "Central Midfielder", "Central Midfielder",
               "Right Winger", "Right Winger", "Striker"),
  Age = c(26, 27, 33, 26, 30, 33, 22, 29, 24, 26, 19)
)

madrid.bench
madrid.academy <- data.frame(
  ID = c(17, 16, 30),
  Name = c("Raul Asencio", "Gonzalo Garcia", "Franco Mastantuono"),
  Position = c("Centre Back", "Striker", "Right Winger"),
  Age = c(22, 21, 18)
)

madrid.academy
madrid.nationality <- data.frame(
  ID = c(1, 12, 24, 22, 18, 14, 8, 5, 15, 7, 10,
         13, 3, 4, 20, 23, 2, 6, 19, 11, 21, 9,
         17, 16, 30),
  Nationality = c("Belgium", "England", "Spain", "Germany", "Spain", "France", "Uruguay", "England",
                  "Turkey", "Brazil", "France", "Ukraine", "Brazil", "Austria", "Spain", "France",
                  "Spain", "France", "Spain", "Brazil", "Spain", "Brazil",
                  "Spain", "Spain", "Argentina")
)

madrid.nationality
madrid.market_value <- data.frame(
  ID = c(1, 12, 24, 22, 18, 14, 8, 5, 15, 7, 10,
         13, 3, 4, 20, 23, 2, 6, 19, 11, 21, 9),
  MarketValue_BillionIDR = c(347.63, 1303.62, 1042.90, 347.63, 608.36, 1303.62, 2259.61, 3128.70,
                             782.17, 2954.88, 3128.70,
                             312.87, 521.45, 104.29, 312.87, 243.34, 139.05, 1042.90, 173.82,
                             1564.35, 695.27, 608.36)
)

madrid.market_value

Inspeksi Data Frame

Sebelum melakukan data wrangling lebih lanjut, langkah penting yang perlu dilakukan adalah inspeksi awal terhadap data frame. Tujuannya agar kita memahami struktur, dimensi, dan isi data yang akan diolah. Pada bagian ini, kita akan melakukan inspeksi pada data utama kita, yaitu madrid.squad.

Mengetahui Jumlah Baris dan Kolom

Mengetahui berapa banyak observasi (baris) dan variabel (kolom) sangat penting di awal analisis.

# Jumlah baris
nrow(madrid.squad)
[1] 11
# Jumlah kolom
ncol(madrid.squad)
[1] 4

Atau jika ingin melihat dimensi secara keseluruhan sekaligus (baris × kolom)

# Dimensi (baris x kolom)
dim(madrid.squad)
[1] 11  4

💡 Catatan: nrow() dan ncol() mengembalikan satu angka, sedangkan dim() mengembalikan vektor berisi dua angka: jumlah baris dan jumlah kolom.

Statistik Ringkasan

Melihat statistik deskriptif dasar seperti nilai minimum, maksimum, dan rata-rata dari setiap kolom numerik.

# Statistik ringkasan
summary(madrid.squad)
       ID            Name             Position              Age       
 Min.   : 1.00   Length:11          Length:11          Min.   :20.00  
 1st Qu.: 7.50   Class :character   Class :character   1st Qu.:22.00  
 Median :12.00   Mode  :character   Mode  :character   Median :25.00  
 Mean   :12.36                                         Mean   :25.27  
 3rd Qu.:16.50                                         3rd Qu.:26.50  
 Max.   :24.00                                         Max.   :33.00  

Output dari fungsi summary() akan menyesuaikan dengan tipe data (class) dari masing-masing kolom: - Untuk kolom bertipe numerik (seperti ID dan Age), summary() akan menampilkan: - Min.: nilai minimum - 1st Qu.: kuartil pertama (Q1) - Median: nilai tengah - Mean: rata-rata - 3rd Qu.: kuartil ketiga (Q3) - Max.: nilai maksimum

  • Untuk kolom bertipe karakter (seperti Name dan Position), summary() akan menampilkan:
    • Panjang vektor (Length)
    • Tipe data (Class)
    • Mode penyimpanan (Mode)

Karena tipe karakter tidak bisa dihitung statistik numeriknya, maka yang ditampilkan hanya informasi umum seperti panjang data dan tipenya.

Jika kolom Position diubah menjadi faktor (factor), maka summary() akan menampilkan frekuensi kemunculan untuk setiap kategori posisinya. Hal ini sangat berguna untuk eksplorasi data kategorik. Contohnya adalah

summary(as.factor(madrid.squad$Position))
Attacking Midfielder   Central Midfielder          Centre Back 
                   2                    1                    2 
Defensive Midfielder           Goalkeeper            Left Back 
                   1                    1                    1 
         Left Winger           Right Back              Striker 
                   1                    1                    1 

Struktur Data Frame

Gunakan str() untuk menampilkan struktur internal dari data frame, termasuk tipe data tiap kolom.

str(madrid.squad)
'data.frame':   11 obs. of  4 variables:
 $ ID      : num  1 12 24 22 18 14 8 5 15 7 ...
 $ Name    : chr  "Thibaut Courtois" "Trent Alexander-Arnold" "Dean Huijsen" "Antonio Rudiger" ...
 $ Position: chr  "Goalkeeper" "Right Back" "Centre Back" "Centre Back" ...
 $ Age     : num  33 26 20 32 22 25 27 22 20 25 ...

Melihat Isi Data

Tampilkan beberapa baris pertama dan baris terakhir untuk mengenali format dan konten data secara langsung.

# Beberapa baris teratas
head(madrid.squad)
# Beberapa baris terbawah
tail(madrid.squad)

Mengakses elemen

Mengakses atau memilih sebagian elemen dari data frame dapat dilakukan menggunakan beberapa operator:

  • [ , ] → operator universal untuk memilih baris dan/atau kolom berdasarkan posisi atau nama
  • [[ ]] → untuk mengambil kolom tunggal berdasarkan nama atau indeks
  • $ → shortcut populer untuk mengakses kolom berdasarkan nama

Berikut ini beberapa contoh menggunakan data frame madrid.squad:

Baris dan Kolom Tertentu

# Baris ke-1, kolom ke-2 (nama pemain)
madrid.squad[1, 2]
[1] "Thibaut Courtois"
# Baris ke-1, kolom "Name"
madrid.squad[1, "Name"]
[1] "Thibaut Courtois"
# Baris ke-1, kolom "Name" menggunakan $
madrid.squad[1, ]$Name
[1] "Thibaut Courtois"

Mengakses Baris dan Kolom Lengkap

# Baris pertama, semua kolom
madrid.squad[1, ]
# Kolom kedua (Name), semua baris
madrid.squad[, 2]
 [1] "Thibaut Courtois"       "Trent Alexander-Arnold" "Dean Huijsen"          
 [4] "Antonio Rudiger"        "Alvaro Carreras"        "Aurelien Tchouameni"   
 [7] "Federico Valverde"      "Jude Bellingham"        "Arda Guler"            
[10] "Vinicius Junior"        "Kylian Mbappe"         
# Kolom "Name", semua baris
madrid.squad[, "Name"]
 [1] "Thibaut Courtois"       "Trent Alexander-Arnold" "Dean Huijsen"          
 [4] "Antonio Rudiger"        "Alvaro Carreras"        "Aurelien Tchouameni"   
 [7] "Federico Valverde"      "Jude Bellingham"        "Arda Guler"            
[10] "Vinicius Junior"        "Kylian Mbappe"         
# Kolom "Name" menggunakan $
madrid.squad$Name
 [1] "Thibaut Courtois"       "Trent Alexander-Arnold" "Dean Huijsen"          
 [4] "Antonio Rudiger"        "Alvaro Carreras"        "Aurelien Tchouameni"   
 [7] "Federico Valverde"      "Jude Bellingham"        "Arda Guler"            
[10] "Vinicius Junior"        "Kylian Mbappe"         

Subset Berdasarkan Posisi Indeks

# Baris 1 sampai 2, semua kolom
madrid.squad[1:2, ]
# Kolom 1 sampai 2, semua baris
madrid.squad[, 1:2]
# Kolom ke-1 dan ke-2, semua baris (dengan c())
madrid.squad[, c(1, 2)]
# Kolom "ID" dan "Name", semua baris
madrid.squad[, c("ID", "Name")]

Filtering Berdasarkan Kondisi

# Semua kolom, hanya baris dengan Age > 25
madrid.squad[madrid.squad$Age > 25, ]

Mengubah Data

Dimungkinkan untuk mengubah/mengupdate nilai dari dataframe. Misalnya, kadang kita perlu memperbarui data karena ada kesalahan pencatatan. Sebagai contoh, posisi dari Arda Guler yang semula Attacking Midfielder berubah menjadi Right Winger.

Jika kita tahu indeks baris tempat Arda Guler berada, kita bisa langsung mengaksesnya berdasarkan posisi, Misalnya kita tahu Arda Guler ada di baris ke-9 dalam madrid.squad.

# Ubah posisi Arda Guler dengan indeks baris
madrid.squad[9, "Position"] <- "Right Winger"

# Cek hasil
madrid.squad[9, ]

Namun, seringkali kita tidak tahu indeks barisnya. Sebagai gantinya, kita bisa menggunakan informasi lain yang unik, misalnya nomor punggung (ID) atau nama pemain:

# Berdasarkan ID
madrid.squad[madrid.squad$ID == 15, "Position"] <- "Right Winger"

# Berdasarkan Name
madrid.squad[madrid.squad$Name == "Arda Guler", "Position"] <- "Right Winger"

Mengurutkan Baris

Mengurutkan baris dapat dilakukan secara ascending (dari kecil ke besar, atau A–Z) maupun descending (dari besar ke kecil, atau Z–A).

Mengurutkan Secara Ascending

Misalnya kita ingin mengurutkan pemain berdasarkan usia dari yang termuda ke tertua:

# Urutkan berdasarkan Age ascending
madrid.squad[order(madrid.squad$Age), ]

Secara default

Mengurutkan Secara Descending

Kita juga bisa mengurutkan secara descending, misalnya untuk melihat siapa pemain paling senior lebih dahulu:

# Urutkan berdasarkan Age descending
madrid.squad[order(madrid.squad$Age, decreasing = TRUE), ]

Mengurutkan dengan Lebih dari Satu Kriteria

Kita juga bisa menggabungkan lebih dari satu kriteria. Misalnya:

  • Urutkan berdasarkan Age (ascending)
  • Jika usia sama, urutkan berdasarkan ID (descending)
# Urutkan berdasarkan Age (asc), lalu ID (desc)
madrid.squad[order(madrid.squad$Age, madrid.squad$ID, 
                   decreasing = c(FALSE, TRUE)), ]

💡 Catatan: Operator order() bisa menampung lebih dari satu variabel pengurutan, dan parameter decreasing dapat berupa vektor logika (TRUE/FALSE) untuk mengatur urutan pada tiap kolom. Secara default, fungsi order() akan mengurutkan data secara ascending (dari kecil ke besar atau A–Z). Jika ingin menurun, gunakan argumen decreasing = TRUE.

Menggabungkan Data Frame

Penggabungan data frame dapat dilakukan secara column-wise (berdasarkan ID atau urutan baris) maupun row-wise (union).

Menggabungkan Kolom Berdasarkan ID

Kita bisa menggabungkan madrid.squad dengan madrid.nationality untuk menambahkan informasi kewarganegaraan pemain ke dalam squad:

merge(madrid.squad, madrid.nationality, by = "ID")

Menggabungkan Kolom Berdasarkan Urutan Baris

Misalnya kita ingin menambahkan informasi gaji dummy (salary) untuk pemain di madrid.squad:

Salary <- c(200, 250, 150, 180, 170, 210, 230, 280, 160, 300, 500)
cbind(madrid.squad, Salary)

Menggabungkan Baris (Union)

Untuk menggabungkan pemain utama dengan pemain cadangan menjadi satu data frame, kita bisa gunakan rbind():

rbind(madrid.squad, madrid.bench)

Jika ingin juga menyertakan pemain akademi, cukup tambahkan:

rbind(madrid.squad, madrid.bench, madrid.academy)

💡 Catatan:

- merge() digunakan ketika ada kolom kunci (key), misalnya ID.
- cbind() digunakan jika ingin menambah kolom baru berdasarkan urutan baris.
- rbind() digunakan untuk menambahkan baris baru dengan struktur kolom yang sama.

Menggabungkan Data Frame Lengkap

Sebagai contoh akhir, kita akan menggabungkan seluruh data frame yang sudah dibuat sebelumnya:

  • Gabungkan seluruh pemain (squad, bench, academy) menjadi madrid.all.players.
  • Tambahkan nationality dengan merge().
  • Tambahkan market value dengan merge().
# Gabungkan semua pemain
madrid.players <- rbind(madrid.squad, madrid.bench)
madrid.all.players <- rbind(madrid.players, madrid.academy)

# Tambahkan nationality
madrid.all.info <- merge(madrid.all.players, madrid.nationality, by = "ID", all.x = TRUE)

# Tambahkan market value
madrid.all.info <- merge(madrid.all.info, madrid.market_value, by = "ID", all.x = TRUE)

# Lihat hasil
madrid.all.info

Secara default, fungsi merge() akan melakukan pengurutan berdasarkan kolom kunci (by). Dalam kasus ini, hasilnya otomatis diurutkan menurut ID. Hal ini terkadang tidak kita inginkan, karena bisa mengubah urutan baris asal (misalnya urutan pemain sesuai squad/bench/academy). Padahal dalam praktik, sering kali kita ingin mempertahankan urutan baris sebagaimana data awal. Untuk itu, kita bisa menambahkan argumen sort = FALSE pada fungsi merge() agar hasil penggabungan tetap mengikuti urutan data frame pertama.

# Tambahkan nationality (pertahankan urutan baris asal)
madrid.all.info <- merge(
  madrid.all.players,
  madrid.nationality,
  by = "ID", all.x = TRUE, sort = FALSE
)

# Tambahkan market value (academy akan NA), tetap pertahankan urutan
madrid.all.info <- merge(
  madrid.all.info,
  madrid.market_value,
  by = "ID", all.x = TRUE, sort = FALSE
)

madrid.all.info

Menambahkan Kolom Baru

Sering kali kita perlu menambahkan kolom turunan untuk memperkaya informasi, misalnya kategori tipe pemain (Starting/Bench/Academy) atau gaji (salary) untuk analisis lebih lanjut. Pembuatan kolom baru dapat dilakukan dengan operasi langsung pada data frame atau dengan melakukan join dari tabel referensi (lookup table).

Menambahkan Kolom Type (Starting/Bench/Academy)

Kita bentuk lookup sederhana yang menetapkan setiap ID ke dalam Starting, Bench, atau Academy sesuai data yang telah kita definisikan sebelumnya. Kolom Type dibuat sebagai factor dengan urutan level: Starting → Bench → Academy.

# Lookup: ID ke Type
type.lookup <- rbind(
  data.frame(ID = madrid.squad$ID,   Type = "Starting"),
  data.frame(ID = madrid.bench$ID,   Type = "Bench"),
  data.frame(ID = madrid.academy$ID, Type = "Academy")
)

# Gabungkan ke madrid.all.info
madrid.all.info <- merge(madrid.all.info, type.lookup, by = "ID", all.x = TRUE, sort = FALSE)

# Jadikan factor berurutan
madrid.all.info$Type <- factor(madrid.all.info$Type,
                               levels = c("Starting", "Bench", "Academy"))

# Cek hasil
head(madrid.all.info[, c("ID", "Name", "Type")])

Menambahkan Kolom Salary

Misalnya kita ingin menambahkan informasi gaji (dummy) ke dalam madrid.all.players. Kita cukup buat vector salary dengan panjang yang sama dengan jumlah baris, lalu gabungkan sesuai urutan.

# Contoh vector salary dummy (dalam miliar IDR per tahun)
Salary <- c(
  500, 450, 300, 280, 260, 310, 330, 400, 270, 420, 600,
  350, 320, 290, 240, 230, 220, 260, 210, 310, 250, 280,
  80, 90, 70
)

# Tambahkan ke data frame
madrid.all.info$Salary <- Salary

head(madrid.all.info[, c("ID", "Name", "Type", "Salary")])

Subsetting Data

Hal penting untuk subsetting data adalah membuat vektor logika sesuai kriteria yang diinginkan. Konsepnya, kita menerjemahkan ide yang kompleks menjadi ekspresi logis di R. Sebelumnya kita sudah punya data frame madrid.all.info

Subsetting Berdasarkan Satu Kondisi

Kita ingin mengambil data khusus untuk pemain Starting saja.

idx <- madrid.all.info$Type == "Starting"
madrid.all.info[idx, ]

Kita juga bisa menuliskan kondisi langsung di dalam fungsi subsetting tanpa membuat variabel idx terlebih dahulu:

madrid.all.info[madrid.all.info$Type == "Starting", ]

Versi lebih ringkas bisa menggunakan fungsi subset():

subset(madrid.all.info, Type == "Starting")

Jika ingin menyimpannya ke sebuah objek baru, maka kita cukup menambahkan assignment:

madrid.starting <- subset(madrid.all.info, Type == "Starting")
madrid.starting

💡 Catatan: subset() enak dipakai untuk filter sederhana, tapi kalau kondisinya kompleks (banyak syarat, fungsi khusus, dll.), biasanya lebih aman menggunakan ekspresi logis di dalam [ ].

Subsetting dengan Beberapa Kondisi

Kadang kita ingin mengambil data dengan lebih dari satu syarat. Misalnya: - Pemain Starting dengan usia di atas 25 tahun, atau - Pemain Bench dengan nilai pasar lebih dari 1000.

myidx <- (madrid.all.info$Type == "Starting" & madrid.all.info$Age > 25) |
         (madrid.all.info$Type == "Bench" & madrid.all.info$MarketValue_BillionIDR > 1000)

madrid.all.info[myidx, ]

Versi lebih ringkas dengan subset() bisa ditulis:

subset(madrid.all.info, 
       (Type == "Starting" & Age > 25) | 
       (Type == "Bench" & MarketValue_BillionIDR > 1000))

Subsetting dengan Missing Value

Pada data kita, pemain akademi tidak memiliki nilai pasar (MarketValue_BillionIDR = NA). Kita bisa memilih hanya pemain yang punya nilai pasar dengan !is.na(). Tanda ! berarti

# Hanya pemain yang nilai pasarnya tidak missing
madrid.clean <- madrid.all.info[!is.na(madrid.all.info$MarketValue_BillionIDR), ]
madrid.clean

Atau dengan subset():

subset(madrid.all.info, !is.na(MarketValue_BillionIDR))

💡 Catatan:

- is.na() digunakan untuk mendeteksi nilai hilang.
- !is.na() artinya pilih baris yang bukan missing value.
- Tanda ! berarti NOT (membalik hasil logika).
- Cara ini penting jika kita ingin memastikan analisis tidak terganggu oleh nilai NA.

Aggregasi

Selain melakukan subsetting, kita juga sering perlu melakukan aggregasi data. Aggregasi berarti merangkum data berdasarkan kategori tertentu, misalnya menghitung rata-rata umur per kategori pemain, atau total nilai pasar per kewarganegaraan. Di R, fungsi bawaan yang sering dipakai adalah aggregate(). Bentuk umumnya adalah:

aggregate(x ~ group, data = df, FUN = fungsi)
  • x : kolom numerik yang ingin dirangkum
  • group : kolom kategorik sebagai pengelompok
  • FUN : fungsi ringkasan, misalnya mean, sum, min, max
# Rata-rata Usia Berdasarkan Tipe Pemain
aggregate(Age ~ Type, data = madrid.all.info, FUN = mean)
# Total Nilai Pasar per Kewarganegaraan
aggregate(MarketValue_BillionIDR ~ Nationality, 
          data = madrid.all.info, 
          FUN = sum, na.rm = TRUE)

Kita juga bisa pakai fungsi ringkasan lain, misalnya min dan max usia per kategori.

aggregate(Age ~ Type, data = madrid.all.info, 
          FUN = function(x) c(min = min(x), max = max(x)))

Untuk aggregasi lebih kompleks dan fleksibel, kita bisa mengeksplorasi lebih lanjut penggunaan package tidyverse di R.

Reshaping Data Frame

Mengubah format data frame (reshaping) adalah proses menata ulang data dari long ke wide atau wide ke long, tergantung kebutuhan analisis dan visualisasi.

  • Long format: setiap baris biasanya mewakili satu pengamatan per variabel/level.
  • Wide format: data lebih melebar, dengan banyak kolom untuk setiap kategori.

Di R, fungsi dasar yang bisa digunakan adalah reshape(). Untuk praktik modern biasanya menggunakan tidyr::pivot_wider() dan tidyr::pivot_longer(), tapi di sini kita menggunakan contoh bawaan R terlebih dahulu.

Untuk kebutuhan praktik reshaping ini, kita buat data simulasi bernama madrid.new.data berikut:

madrid.new.data <- data.frame(
  ID = rep(c(7, 10, 5, 15, 11), each = 3),
  Name = rep(c("Vinicius Junior", "Kylian Mbappe", "Jude Bellingham",
               "Arda Guler", "Rodrygo"), each = 3),
  Competition = rep(c("La Liga", "Copa del Rey", "UEFA Champions League"), times = 5),
  Appearances = c(32, 5, 11,   34, 6, 12,   30, 4, 10,   18, 3, 6,   28, 4, 11),
  Goals       = c(18, 2, 6,    25, 3, 10,   16, 1, 5,    6,  1, 2,   12, 2, 4)
)

madrid.new.data

Long to Wide

Untuk mengubah data dari long ke wide dengan fungsi reshape(), ada dua argumen utama yang harus digunakan:

  • timevar → kolom yang berisi kategori yang akan diputar menjadi kolom.
  • idvar → kolom identitas unik yang tetap dipertahankan.

Contoh: Contohnya, jika kita ingin mengubah data madrid.new.data supaya setiap kompetisi (La Liga, Copa del Rey, UEFA Champions League) menjadi kolom terpisah.

madrid.wide <- reshape(
  madrid.new.data,
  idvar   = c("ID", "Name"),       # kolom identitas unik yang tetap dipertahankan
  timevar = "Competition",         # kolom kategori yang diputar jadi nama kolom baru
  direction = "wide"               # arah perubahan data: dari long → wide
)

madrid.wide
ID Name Appearances.La Liga Goals.La Liga Appearances.Copa del Rey Goals.Copa del Rey Appearances.UEFA Champions League Goals.UEFA Champions League
1 7 Vinicius Junior 32 18 5 2 11 6
4 10 Kylian Mbappe 34 25 6 3 12 10
7 5 Jude Bellingham 30 16 4 1 10 5
10 15 Arda Guler 18 6 3 1 6 2
13 11 Rodrygo 28 12 4 2 11 4

Wide to Long

Untuk mengubah data dari wide ke long dengan fungsi reshape(), ada dua argumen utama yang harus digunakan:

  • varying → objek list yang berisi nama-nama kolom dalam format wide yang ingin digabungkan kembali.
  • v.names → nama kolom baru yang akan menampung nilai pada format long.

Contohnya, jika kita ingin mengembalikan madrid.wide ke bentuk long agar lebih mudah difilter dan divisualisasikan:

# Ambil nama kolom wide
apps_cols <- grep("^Appearances\\.", names(madrid.wide), value = TRUE)
goals_cols <- grep("^Goals\\.", names(madrid.wide), value = TRUE)
apps_cols
[1] "Appearances.La Liga"               "Appearances.Copa del Rey"         
[3] "Appearances.UEFA Champions League"
apps_cols
[1] "Appearances.La Liga"               "Appearances.Copa del Rey"         
[3] "Appearances.UEFA Champions League"
goals_cols
[1] "Goals.La Liga"               "Goals.Copa del Rey"         
[3] "Goals.UEFA Champions League"
madrid.long <- reshape(
  madrid.wide,
  varying = list(apps_cols, goals_cols),   # daftar kolom wide yang mau dilebur kembali (list per variabel)
  v.names = c("Appearances", "Goals"),     # nama kolom baru hasil gabungan nilai
  direction = "long"                       # arah perubahan data: dari wide → long
)

madrid.long
ID Name time Appearances Goals id
1.1 7 Vinicius Junior 1 32 18 1
2.1 10 Kylian Mbappe 1 34 25 2
3.1 5 Jude Bellingham 1 30 16 3
4.1 15 Arda Guler 1 18 6 4
5.1 11 Rodrygo 1 28 12 5
1.2 7 Vinicius Junior 2 5 2 1
2.2 10 Kylian Mbappe 2 6 3 2
3.2 5 Jude Bellingham 2 4 1 3
4.2 15 Arda Guler 2 3 1 4
5.2 11 Rodrygo 2 4 2 5
1.3 7 Vinicius Junior 3 11 6 1
2.3 10 Kylian Mbappe 3 12 10 2
3.3 5 Jude Bellingham 3 10 5 3
4.3 15 Arda Guler 3 6 2 4
5.3 11 Rodrygo 3 11 4 5

Muhammad Yusran
Program Studi Magister Statistika dan Sains Data
Sekolah Sains Data, Matematika, dan Informatika
IPB University

Email: muhammadyusran@apps.ipb.ac.id
LinkedIn: Muhammad Yusran
Instagram: mhammad.yusran_