Fungsi pivot menata ulang letak nilai antarkolom tanpa mengubah isinya. Topik ini membahas pivot_longer() untuk mengubah tabel lebar menjadi tabel panjang, pivot_wider() untuk mengubahnya kembali, peredaran bolak-balik (roundtrip) yang memastikan keduanya saling melengkapi, serta argumen values_fill untuk menangani kekosongan data. Contohnya memakai rekap nilai ujian per kelas per semester yang sama dari awal sampai akhir.
Mengubah tabel lebar menjadi panjang dengan pivot_longer#
Tabel lebar menyimpan setiap semester di kolom tersendiri, seperti rekap rata-rata nilai ujian berikut. Setiap kelas menempati satu baris, sedangkan tiga semester menempati tiga kolom nilai. Perhatikan bahwa nama tiga kolom terakhir adalah nilai, bukan nama variabel.
library(tidyverse)
rekap <- tribble(
~kelas, ~`Ganjil 2024`, ~`Genap 2024`, ~`Ganjil 2025`,
"7A", 78, 82, 80,
"7B", 74, 79, 77
)
rekap── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# A tibble: 2 × 4
kelas `Ganjil 2024` `Genap 2024` `Ganjil 2025`
<chr> <dbl> <dbl> <dbl>
1 7A 78 82 80
2 7B 74 79 77Nama kolom Ganjil 2024, Genap 2024, dan Ganjil 2025 sebenarnya adalah nilai dari variabel semester, sedangkan isinya adalah nilai dari variabel rata_rata. Fungsi pivot_longer() memindahkan nama-nama kolom tersebut beserta isinya sekaligus. Argumen cols menentukan kolom yang dipindahkan, argumen names_to menamai kolom baru penampung nama kolom lama, dan argumen values_to menamai kolom penampung isinya.
panjang <- pivot_longer(rekap, cols = -kelas, names_to = "semester", values_to = "rata_rata")
panjang# A tibble: 6 × 3
kelas semester rata_rata
<chr> <chr> <dbl>
1 7A Ganjil 2024 78
2 7A Genap 2024 82
3 7A Ganjil 2025 80
4 7B Ganjil 2024 74
5 7B Genap 2024 79
6 7B Ganjil 2025 77Selektor pada cols mengikuti aturan dplyr. Tanda minus pada cols = -kelas berarti seluruh kolom kecuali kelas dipindahkan, sedangkan selektor lain seperti starts_with() juga dapat dipakai apabila kolom nilai berbagi awalan nama. Hasilnya berupa enam baris, yaitu dua kelas dikali tiga semester, dengan satu nilai rata_rata per baris.
Data dalam bentuk lebar sering dihasilkan lembar kerja yang disusun untuk dibaca manusia, sehingga keadaan ini ditemui hampir setiap kali data diimpor. Pivot pertama yang dilakukan pada data baru dengan demikian biasanya berarah dari lebar ke panjang, sebelum penghitungan lain dimulai.
Nama yang tersisa pada kolom semester juga dapat dirapikan dengan argumen names_prefix. Apabila kolom semula bernama ganjil_2024 dan ganjil_2025, argumen names_prefix = "ganjil_" membuang awalan itu dari setiap nama, sehingga isi kolom baru tidak membawa ulang teks yang sudah tersirat pada namanya.
Mengubah tabel panjang menjadi lebar dengan pivot_wider#
Perubahan sebaliknya dilakukan oleh pivot_wider(). Argumen names_from menyebut kolom yang isinya menjadi nama kolom baru. Argumen values_from menyebut kolom yang isinya mengisi sel-sel kolom baru tersebut. Penerapan keduanya pada tabel panjang mengembalikan bentuk semula.
pivot_wider(panjang, names_from = semester, values_from = rata_rata)# A tibble: 2 × 4
kelas `Ganjil 2024` `Genap 2024` `Ganjil 2025`
<chr> <dbl> <dbl> <dbl>
1 7A 78 82 80
2 7B 74 79 77Kolom semester musnah karena isinya telah menyebar menjadi tiga kolom, dan tabel hasil hanya memuat dua baris, satu per kelas. Urutan kolom hasil mengikuti urutan kemunculan nilainya pada data, sehingga Ganjil 2024, Genap 2024, dan Ganjil 2025 tampil berurutan. Fungsi ini lazim dipakai menjelang penyajian, misalnya sebelum tabel dipindahkan ke laporan atau lembar kerja yang dibaca manusia.
Memeriksa peredaran bolak-balik#
Apabila pivot_wider() dan pivot_longer() dipasangkan dengan argumen yang saling mencerminkan, hasil akhirnya identik dengan data awal. Sifat ini disebut peredaran bolak-balik dan menjadi pemeriksaan cepat apabila keraguan muncul tentang kebenaran hasil pivot. Kedua fungsi memang saling berkebalikan, sehingga kesalahan pada satu sisi langsung terlihat pada perbandingannya.
identical(
pivot_longer(pivot_wider(panjang, names_from = semester, values_from = rata_rata),
cols = -kelas, names_to = "semester", values_to = "rata_rata"),
panjang
)[1] TRUENilai TRUE pada keluaran berarti tabel hasil peredaran identik dengan tabel panjang awal, termasuk urutan kolom dan tipe datanya. Pemeriksaan seperti ini murah dilakukan, tetapi cukup untuk menangkap kesalahan argumen yang sering terjadi, misalnya names_to dan values_to yang tertukar. Apabila hasilnya FALSE, bandingkan nama dan urutan kolom kedua tabel dengan names() sebelum mencari kesalahan argumennya.
Mengisi kekosongan data dengan values_fill#
Tabel panjang yang nyata sering tidak lengkap. Kekosongan seperti ini wajar terjadi, misalnya karena ujian satu kelas belum dilaksanakan atau datanya gagal terekam. Apabila satu kombinasi kelas dan semester tidak memiliki baris, pivot_wider() menyisakan sel kosong berupa NA.
panjang_kurang <- tribble(
~kelas, ~semester, ~rata_rata,
"7A", "Ganjil", 78,
"7A", "Genap", 82,
"7B", "Ganjil", 74
)
pivot_wider(panjang_kurang, names_from = semester, values_from = rata_rata)# A tibble: 2 × 3
kelas Ganjil Genap
<chr> <dbl> <dbl>
1 7A 78 82
2 7B 74 NANilai NA pada kolom Genap menandakan kelas 7B belum memiliki nilai rata_rata untuk semester tersebut, dan posisi selnya tetap dipertahankan agar tabel tetap sejajar. Apabila kekosongan dibiarkan, penghitungan lanjutan yang menyentuh kolom itu ikut menghasilkan NA. Argumen values_fill mengganti kekosongan semacam ini dengan nilai tertentu.
pivot_wider(panjang_kurang, names_from = semester, values_from = rata_rata, values_fill = 0)# A tibble: 2 × 3
kelas Ganjil Genap
<chr> <dbl> <dbl>
1 7A 78 82
2 7B 74 0Argumen values_fill menerima satu nilai untuk seluruh kolom nilai, atau vektor bernama (named vector) untuk mengatur isian per kolom. Isian yang umum adalah 0 untuk pencacahan kejadian dan teks kosong untuk kolom karakter. Sebelum memilih isian, tentukan dahulu apakah kekosongan berarti data belum ada atau data memang bernilai nol, karena kedua makna itu menuntut perlakuan berbeda pada analisis.
Kesalahan umum#
Kesalahan pertama adalah memindahkan kolom identitas bersama kolom nilainya. Apabila cols menyertakan kolom kelas, isi kelas ikut dipindahkan ke kolom nilai, dan karena kelas bertipe character sedangkan rata_rata bertipe double, penggabungan kedua tipe itu langsung gagal. Selektor yang terlalu luas, misalnya everything(), adalah penyebab yang paling sering.
pivot_longer(rekap, cols = everything(), names_to = "semester", values_to = "rata_rata")Error in pivot_longer(rekap, cols = everything(), names_to = "semester", values_to = "rata_rata") : Can't combine `kelas` <character> and `Ganjil 2024` <double>.Pesan Can't combine berarti kolom-kolom yang dipindahkan bertipe berbeda sehingga tidak dapat ditempatkan pada satu kolom nilai. Perbaikannya adalah menyisihkan kolom identitas dengan cols = -kelas, sehingga hanya kolom nilai yang dipindahkan. Apabila memang kolom campuran perlu dipertahankan, samakan tipe kolom-kolomnya terlebih dahulu lewat konversi.
Kesalahan kedua adalah memanggil pivot_wider() pada tabel panjang yang memuat kunci ganda, yaitu kombinasi kelas dan semester yang muncul lebih dari satu kali. Kunci ganda lazim muncul ketika pengukuran diulang atau data digabung dari lebih dari satu sumber. tidyr tidak menebak cara merapatkan nilainya, sehingga kolom hasil berubah menjadi list dan sebuah peringatan dikeluarkan.
ganda <- tribble(
~kelas, ~semester, ~rata_rata,
"7A", "Ganjil", 78,
"7A", "Ganjil", 80
)
pivot_wider(ganda, names_from = semester, values_from = rata_rata)Warning: Values from `rata_rata` are not uniquely identified; output will contain
list-cols.
• Use `values_fn = list` to suppress this warning.
• Use `values_fn = {summary_fun}` to summarise duplicates.
• Use the following dplyr code to identify duplicates.
{data} |>
dplyr::summarise(n = dplyr::n(), .by = c(kelas, semester)) |>
dplyr::filter(n > 1L)
# A tibble: 1 × 2
kelas Ganjil
<chr> <list>
1 7A <dbl [2]>Peringatan Values from rata_rata are not uniquely identified berarti satu sel akan menampung dua nilai sekaligus. Perbaikan yang benar dilakukan di hulu, yaitu merapatkan nilai ganda terlebih dahulu dengan group_by() dan summarize(), misalnya mengambil rata-ratanya, sehingga setiap kombinasi kelas dan semester hanya muncul satu kali. Argumen values_fn memang dapat menengahi duplikat saat pivot, tetapi keputusan merapatkan data sebaiknya disadari, bukan tersembunyi di dalam pembentukan bentuk.
Ringkasan#
pivot_longer()memindahkan kolom terpilih menjadi dua kolom baru, yaitu nama (names_to) dan nilai (values_to).pivot_wider()menyebar satu kolom menjadi banyak kolom berdasarkannames_fromdanvalues_from.- Pasangan keduanya yang argumennya saling mencerminkan mengembalikan data awal, dan fungsi
identical()memeriksanya. - Kombinasi tanpa baris menjadi NA, dan
values_fillmenggantinya dengan nilai tertentu. - Kunci ganda pada
pivot_wider()menghasilkan peringatan dan kolom list, sehingga duplikatnya dirapatkan terlebih dahulu.
Referensi#
- tidyr: Tidy Messy Data — tidyverse — dokumentasi resmi tidyr, termasuk halaman pivot_longer dan pivot_wider beserta seluruh argumennya.
- R for Data Science, edisi ke-2 — Wickham, Çetinkaya-Rundel, Grolemund — bagian Tidy data membahas pivot sebagai alat utama membentuk ulang tabel.